<?php

namespace App\Console\Commands;

use App\Jobs\GenerateDocumentPreview;
use App\Models\Document;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class GenerateMissingPreviews extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'documents:generate-previews {--now : Run the preview job synchronously instead of queueing it} {--limit=100 : Max documents to process}';

    /**
     * The console command description.
     */
    protected $description = 'Queue or run preview generation for DOC/DOCX documents that are missing a generated preview.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $limit = (int) $this->option('limit');
        $now = (bool) $this->option('now');

        $docs = Document::query()
            ->whereNull('deleted_at')
            ->where(function ($q) {
                $q->whereRaw("lower(extension) in ('doc','docx')");
            })
            ->orderByDesc('updated_at')
            ->limit($limit * 5)
            ->get();

        if ($docs->isEmpty()) {
            $this->info('No documents requiring preview generation.');

            return self::SUCCESS;
        }

        $this->info('Scanning '.$docs->count().' candidate document(s) for (re)generation...');
        $dispatched = 0;
        foreach ($docs as $doc) {
            // Verify source file exists on disk or under public before dispatching
            $disk = $doc->disk ?: 'public';
            $relPath = ltrim($doc->path ?? '', '/\\');
            if (str_starts_with($relPath, 'public/')) {
                $relPath = substr($relPath, 7);
            }
            $has = Storage::disk($disk)->exists($relPath);
            if (! $has) {
                $publicFull = public_path($relPath);
                $real = @realpath($publicFull);
                $publicRoot = @realpath(public_path());
                $realN = $real ? str_replace('\\\\', '/', $real) : null;
                $rootN = $publicRoot ? str_replace('\\\\', '/', $publicRoot) : null;
                $has = $realN && $rootN && str_starts_with($realN, $rootN) && is_file($real);
            }
            if (! $has) {
                $this->warn('Skipping doc '.$doc->id.' (source file missing): '.$doc->path);

                continue;
            }

            // Determine if (re)generation is required
            $needs = false;
            $previewDisk = config('files.preview_disk', 'public');
            if (empty($doc->preview_path)) {
                $needs = true;
            } else {
                $existsPreview = Storage::disk($previewDisk)->exists($doc->preview_path);
                if (! $existsPreview) {
                    $needs = true;
                } elseif ($doc->preview_generated_at && $doc->updated_at && $doc->updated_at->gt($doc->preview_generated_at)) {
                    $needs = true;
                }
            }
            if (! $needs) {
                continue;
            }

            if ($now) {
                GenerateDocumentPreview::dispatchSync($doc->id);
            } else {
                GenerateDocumentPreview::dispatch($doc->id);
            }
            $dispatched++;
        }

        $this->info(($now ? 'Ran' : 'Queued').' preview generation for '.$dispatched.' document(s).');

        return self::SUCCESS;
    }
}
