<?php

namespace App\Console\Commands;

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

class MissingFilesCommand extends Command
{
    protected $signature = 'documents:missing-files
                            {--output= : Path to write CSV output (defaults to stdout)}';

    protected $description = 'Generate a CSV of documents in the database with no corresponding file on the public disk.';

    public function handle(): int
    {
        $outputPath = $this->option('output');
        $toStdout = $outputPath === null;

        $handle = $toStdout ? fopen('php://stdout', 'w') : fopen($outputPath, 'w');

        if ($handle === false) {
            $this->error("Cannot open output path: {$outputPath}");
            return 1;
        }

        // When piping CSV to stdout, write progress to stderr so they don't mix
        $progress = $toStdout
            ? $this->output->getErrorOutput()
            : $this->output;

        $total = Document::count();
        $progress->writeln("<info>Scanning {$total} documents for missing files...</info>");

        fputcsv($handle, [
            'document_id',
            'display_name',
            'file_name',
            'owner_type',
            'owner_id',
            'expected_path',
            'file_size_bytes',
            'created_at',
        ]);

        $missing = 0;

        Document::with('owner')->chunkById(200, function ($documents) use ($handle, &$missing) {
            foreach ($documents as $document) {
                $owner = $document->owner;

                if ($owner === null) {
                    $ownerType = 'MISSING';
                    $expectedPath = 'UNKNOWN';
                } else {
                    $basePath = rtrim($owner->getDocumentStoragePath(), '/');
                    $expectedPath = $basePath . '/' . $document->file_name;
                    $ownerType = class_basename($owner);

                    if (Storage::disk('public')->exists($expectedPath)) {
                        continue;
                    }
                }

                $missing++;

                fputcsv($handle, [
                    $document->id,
                    $document->display_name,
                    $document->file_name,
                    $ownerType,
                    $document->owner_id,
                    $expectedPath,
                    $document->getRawOriginal('file_size'),
                    $document->created_at,
                ]);
            }
        });

        if (!$toStdout) {
            fclose($handle);
        }

        $progress->writeln('');
        $progress->writeln("<comment>Found {$missing} document(s) with missing files.</comment>");

        if (!$toStdout) {
            $this->info("CSV written to: {$outputPath}");
        }

        return 0;
    }
}
