<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\CreatorAiBiography;
use App\Models\User;
use App\Services\AiBiography\AiBiographyValidator;
use Illuminate\Console\Command;

/**
 * Validate stored AI biographies against the current validator rules.
 *
 * Useful after hardening the validator (e.g. v1.1 upgrade) to identify bios
 * generated under older, looser rules that no longer pass.
 *
 * Flagged biographies have needs_review=true set but are NOT hidden or deleted.
 *
 * Usage:
 *   php artisan ai-biography:validate
 *   php artisan ai-biography:validate {user_id}
 *   php artisan ai-biography:validate --dry-run
 */
final class ValidateAiBiographyCommand extends Command
{
    protected $signature = 'ai-biography:validate
                            {user_id? : Validate biography for a single creator}
                            {--dry-run : Report failures without updating records}
                            {--limit=500 : Maximum number of records to check}';

    protected $description = 'Validate stored AI biographies against current validator rules';

    public function handle(AiBiographyValidator $validator): int
    {
        $userId = $this->argument('user_id');
        $dryRun = (bool) $this->option('dry-run');
        $limit  = max(1, (int) $this->option('limit'));

        if ($userId !== null) {
            return $this->handleSingle((int) $userId, $validator, $dryRun);
        }

        return $this->handleBatch($validator, $dryRun, $limit);
    }

    private function handleSingle(int $userId, AiBiographyValidator $validator, bool $dryRun): int
    {
        $user = User::query()->where('id', $userId)->whereNull('deleted_at')->first();

        if ($user === null) {
            $this->error("User #{$userId} not found.");

            return self::FAILURE;
        }

        $record = CreatorAiBiography::query()
            ->where('user_id', $userId)
            ->where('is_active', true)
            ->latest()
            ->first();

        if ($record === null) {
            $this->line("User #{$userId} ({$user->username}): no active biography.");

            return self::SUCCESS;
        }

        if ($record->is_user_edited) {
            $this->line("User #{$userId} ({$user->username}): biography is user-edited — skipping.");

            return self::SUCCESS;
        }

        $errors = $validator->validate(
            (string) $record->text,
            $record->input_quality_tier ?? 'rich',
        );

        if ($errors === []) {
            $this->info("User #{$userId} ({$user->username}): ✓ valid");
        } else {
            $this->warn("User #{$userId} ({$user->username}): ✗ " . implode('; ', $errors));

            if (! $dryRun) {
                $record->update(['needs_review' => true]);
            }
        }

        return self::SUCCESS;
    }

    private function handleBatch(AiBiographyValidator $validator, bool $dryRun, int $limit): int
    {
        $this->info('Validating stored AI biographies against current rules...');

        $checked = 0;
        $passed  = 0;
        $failed  = 0;
        $skipped = 0;

        CreatorAiBiography::query()
            ->where('is_active', true)
            ->whereNotNull('text')
            ->where('is_user_edited', false)
            ->whereIn('status', [
                CreatorAiBiography::STATUS_GENERATED,
                CreatorAiBiography::STATUS_APPROVED,
            ])
            ->limit($limit)
            ->chunkById(100, function ($records) use ($validator, $dryRun, &$checked, &$passed, &$failed, &$skipped): void {
                foreach ($records as $record) {
                    $checked++;

                    $errors = $validator->validate(
                        (string) $record->text,
                        $record->input_quality_tier ?? 'rich',
                    );

                    if ($errors === []) {
                        $passed++;
                    } else {
                        $failed++;
                        $this->warn("  [user:{$record->user_id}] id:{$record->id} — " . implode('; ', $errors));

                        if (! $dryRun) {
                            $record->update(['needs_review' => true]);
                        }
                    }
                }
            });

        $dryTag = $dryRun ? ' [dry-run — no records updated]' : '';
        $this->info("Done. checked={$checked}  passed={$passed}  failed/flagged={$failed}{$dryTag}");

        return self::SUCCESS;
    }
}
