<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Story;
use App\Models\StoryAuthor;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Throwable;

/**
 * Migrate legacy interview records into the new Stories system.
 *
 * Usage:
 *   php artisan stories:migrate-legacy
 *   php artisan stories:migrate-legacy --dry-run
 *   php artisan stories:migrate-legacy --legacy-connection=legacy --chunk=100
 *
 * Idempotent: running multiple times will not duplicate records.
 * Legacy records are identified via `legacy_interview_id` column on stories table.
 */
final class MigrateStoriesCommand extends Command
{
    protected $signature = 'stories:migrate-legacy
        {--chunk=50           : number of records to process per batch}
        {--dry-run            : preview migration without persisting changes}
        {--legacy-connection= : DB connection name for legacy database (default: uses default connection)}
        {--legacy-table=interviews : legacy interviews table name}
    ';

    protected $description = 'Migrate legacy interview records into the new nova Stories system (idempotent)';

    public function handle(): int
    {
        $chunk      = max(1, (int) $this->option('chunk'));
        $dryRun     = (bool) $this->option('dry-run');
        $legacyConn = $this->option('legacy-connection') ?: null;
        $table      = (string) $this->option('legacy-table');

        $this->info('Nova Stories — legacy interview migration');
        $this->info("Table: {$table}  |  Chunk: {$chunk}  |  Dry-run: " . ($dryRun ? 'YES' : 'NO'));
        $this->newLine();

        try {
            $db = $legacyConn ? DB::connection($legacyConn) : DB::connection();
            // Quick existence check
            $db->table($table)->limit(1)->get();
        } catch (Throwable $e) {
            $this->error("Cannot access table `{$table}`: " . $e->getMessage());
            return self::FAILURE;
        }

        $inserted  = 0;
        $skipped   = 0;
        $failed    = 0;

        $db->table($table)->orderBy('id')->chunkById($chunk, function ($rows) use (
            $dryRun, &$inserted, &$skipped, &$failed
        ) {
            foreach ($rows as $row) {
                $legacyId = (int) ($row->id ?? 0);

                if (! $legacyId) {
                    $skipped++;
                    continue;
                }

                // Idempotency: skip if already migrated
                if (Story::where('legacy_interview_id', $legacyId)->exists()) {
                    $skipped++;
                    continue;
                }

                try {
                    // ── Resolve / create author ──────────────────────────────
                    $authorName   = $this->coerceString($row->username ?? $row->author ?? $row->uname ?? '');
                    $authorAvatar = $this->coerceString($row->icon ?? $row->avatar ?? '');

                    $author = null;
                    if ($authorName) {
                        $author = StoryAuthor::firstOrCreate(
                            ['name' => $authorName],
                            ['avatar' => $authorAvatar ?: null]
                        );
                    }

                    // ── Build slug ───────────────────────────────────────────
                    $rawTitle = $this->coerceString(
                        $row->headline ?? $row->title ?? $row->subject ?? ''
                    ) ?: 'interview-' . $legacyId;

                    $slugBase = Str::slug(Str::limit($rawTitle, 180));
                    $slug     = $slugBase ?: 'interview-' . $legacyId;

                    // Ensure uniqueness
                    $slug = $this->uniqueSlug($slug);

                    // ── Excerpt ──────────────────────────────────────────────
                    $fullContent = $this->coerceString(
                        $row->content ?? $row->tekst ?? $row->body ?? $row->text ?? ''
                    );

                    $excerpt = $this->coerceString($row->excerpt ?? $row->intro ?? $row->lead ?? '');
                    if (! $excerpt && $fullContent) {
                        $excerpt = Str::limit(strip_tags($fullContent), 200);
                    }

                    // ── Cover image ──────────────────────────────────────────
                    $coverRaw   = $this->coerceString($row->pic ?? $row->image ?? $row->cover ?? $row->photo ?? '');
                    $coverImage = $coverRaw ? 'legacy/interviews/' . ltrim($coverRaw, '/') : null;

                    // ── Published date ───────────────────────────────────────
                    $publishedAt = null;
                    foreach (['datum', 'published_at', 'date', 'created_at'] as $field) {
                        $val = $row->{$field} ?? null;
                        if ($val) {
                            $ts = strtotime((string) $val);
                            if ($ts) {
                                $publishedAt = date('Y-m-d H:i:s', $ts);
                                break;
                            }
                        }
                    }

                    if ($dryRun) {
                        $this->line("  [DRY-RUN] Would import: #{$legacyId} → {$slug}");
                        $inserted++;
                        continue;
                    }

                    Story::create([
                        'slug'                => $slug,
                        'title'               => Str::limit($rawTitle, 255),
                        'excerpt'             => $excerpt ?: null,
                        'content'             => $fullContent ?: null,
                        'cover_image'         => $coverImage,
                        'author_id'           => $author?->id,
                        'views'               => max(0, (int) ($row->views ?? $row->hits ?? 0)),
                        'featured'            => false,
                        'status'              => 'published',
                        'published_at'        => $publishedAt,
                        'legacy_interview_id' => $legacyId,
                    ]);

                    $this->line("  Imported: #{$legacyId} → {$slug}");
                    $inserted++;

                } catch (Throwable $e) {
                    $failed++;
                    $this->warn("  FAILED #{$legacyId}: " . $e->getMessage());
                    Log::warning("stories:migrate-legacy failed for id={$legacyId}", ['error' => $e->getMessage()]);
                }
            }
        });

        $this->newLine();
        $this->info("Migration complete.");
        $this->table(
            ['Inserted', 'Skipped (existing)', 'Failed'],
            [[$inserted, $skipped, $failed]]
        );

        return $failed > 0 ? self::FAILURE : self::SUCCESS;
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    private function coerceString(mixed $value, string $default = ''): string
    {
        if ($value === null) {
            return $default;
        }
        $str = trim((string) $value);
        return $str !== '' ? $str : $default;
    }

    /**
     * Ensure the slug is unique, appending a numeric suffix if needed.
     */
    private function uniqueSlug(string $slug): string
    {
        if (! Story::where('slug', $slug)->exists()) {
            return $slug;
        }

        $i = 2;
        do {
            $candidate = $slug . '-' . $i++;
        } while (Story::where('slug', $candidate)->exists());

        return $candidate;
    }
}
