<?php

declare(strict_types=1);

use App\Models\Artwork;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

require __DIR__ . '/../vendor/autoload.php';
$app = require __DIR__ . '/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

$options = getopt('', ['id::', 'limit::', 'publish']);
$id = isset($options['id']) ? (int) $options['id'] : null;
$limit = isset($options['limit']) ? max(1, (int) $options['limit']) : 25;
$publish = array_key_exists('publish', $options);

$brokenQuery = Artwork::query()->where(function ($query): void {
    $query->where('file_path', 'pending')
        ->orWhereNull('hash')
        ->orWhereNull('file_ext')
        ->orWhereNull('thumb_ext')
        ->orWhere('file_name', 'pending')
        ->orWhere('file_size', 0)
        ->orWhere('width', '<=', 1)
        ->orWhere('height', '<=', 1);
});

if ($id && $id > 0) {
    $brokenQuery->whereKey($id);
}

$rows = $brokenQuery->orderBy('id')->limit($limit)->get();
if ($rows->isEmpty()) {
    fwrite(STDOUT, "No matching broken artworks found.\n");
    exit(0);
}

$storageRoot = rtrim((string) config('uploads.storage_root'), DIRECTORY_SEPARATOR);
$fixed = 0;
$skipped = 0;

$makeUniqueSlug = static function (Artwork $artwork, string $title): string {
    $base = Str::slug($title);
    if ($base === '') {
        $base = 'artwork-' . $artwork->id;
    }

    $slug = $base;
    $suffix = 2;
    while (Artwork::query()->where('slug', $slug)->where('id', '!=', $artwork->id)->exists()) {
        $slug = $base . '-' . $suffix;
        $suffix++;
    }

    return $slug;
};

foreach ($rows as $artwork) {
    $files = DB::table('artwork_files')
        ->where('artwork_id', $artwork->id)
        ->get(['variant', 'path', 'mime', 'size'])
        ->keyBy('variant');

    $orig = $files->get('orig');
    if (! $orig || empty($orig->path)) {
        fwrite(STDOUT, "[SKIP] {$artwork->id}: no orig variant in artwork_files\n");
        $skipped++;
        continue;
    }

    $origPath = (string) $orig->path;
    $absolute = $storageRoot . DIRECTORY_SEPARATOR . str_replace(['/', '\\\\'], DIRECTORY_SEPARATOR, $origPath);

    $hash = null;
    $fileSize = (int) ($orig->size ?? 0);
    $width = (int) $artwork->width;
    $height = (int) $artwork->height;

    if (is_file($absolute)) {
        $hash = hash_file('sha256', $absolute) ?: null;
        $actualSize = @filesize($absolute);
        if (is_int($actualSize) && $actualSize > 0) {
            $fileSize = $actualSize;
        }

        $dimensions = @getimagesize($absolute);
        if (is_array($dimensions) && isset($dimensions[0], $dimensions[1])) {
            $width = max(1, (int) $dimensions[0]);
            $height = max(1, (int) $dimensions[1]);
        }
    }

    $ext = strtolower((string) pathinfo($origPath, PATHINFO_EXTENSION));
    if ($ext === '') {
        $ext = 'webp';
    }

    $title = trim((string) ($artwork->title ?? ''));
    if ($title === '') {
        $title = 'Artwork ' . $artwork->id;
    }

    $slug = $makeUniqueSlug($artwork, $title);

    $updates = [
        'title' => $title,
        'slug' => $slug,
        'file_name' => basename($origPath),
        'file_path' => $origPath,
        'file_size' => max(1, $fileSize),
        'mime_type' => (string) ($orig->mime ?: 'image/webp'),
        'hash' => $hash ?: (string) ($artwork->hash ?? ''),
        'file_ext' => $ext,
        'thumb_ext' => $ext,
        'width' => max(1, $width),
        'height' => max(1, $height),
    ];

    if ($publish) {
        $updates['is_public'] = true;
        $updates['is_approved'] = true;
        $updates['published_at'] = $artwork->published_at ?: now();
    }

    if (empty($updates['hash'])) {
        fwrite(STDOUT, "[SKIP] {$artwork->id}: hash could not be recovered from file\n");
        $skipped++;
        continue;
    }

    Artwork::query()->whereKey($artwork->id)->update($updates);
    fwrite(STDOUT, "[FIXED] {$artwork->id}: {$updates['file_path']} | hash=" . substr((string) $updates['hash'], 0, 12) . "...\n");
    $fixed++;
}

fwrite(STDOUT, "Done. fixed={$fixed} skipped={$skipped}\n");
exit(0);
