<?php

namespace App\Jobs;

use App\MediaRepository;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Mtc\ContentManager\Contracts\Media;
use Mtc\ContentManager\Contracts\MediaUse;
use Mtc\ContentManager\ImageSize;
use Mtc\ContentManager\Jobs\RegenerateSizesForMediaFileJob;
use Mtc\MercuryDataModels\ApiNotification;

class VerifyVehicleProviderMediaJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public $timeout = 1800;

    public function __construct(private readonly Carbon $since)
    {
        $this->onQueue('bulk-media');
    }

    public function handle(MediaRepository $repository): void
    {
        // Resolving MediaRepository configures the tenant-aware media disk.
        unset($repository);
        $disk = Storage::disk(Config::get('filesystems.default_media'));
        $regeneratedMediaIds = [];

        MediaUse::query()
            ->where('owner_type', 'vehicle')
            ->where('created_at', '>=', $this->since)
            ->whereHas('media', fn ($query) => $query->whereNotNull('image_provider'))
            ->with('media')
            ->chunkById(200, function (Collection $chunk) use ($disk, &$regeneratedMediaIds) {
                $chunk->each(fn (MediaUse $use) => $this->verifyUse($use, $disk, $regeneratedMediaIds));
            });
    }

    private function verifyUse(MediaUse $use, Filesystem $disk, array &$regeneratedMediaIds): void
    {
        $media = $use->media;

        if (!$media) {
            return;
        }

        if (!$disk->exists($media->path . '/' . $media->src)) {
            $this->removeOrphanMedia($media, $use);
            return;
        }

        if (in_array($media->id, $regeneratedMediaIds, true)) {
            return;
        }

        $missing = collect($use->allowed_sizes ?? [])
            ->filter(fn (string $dimensions) => !$disk->exists(
                ImageSize::fromArray(self::dimensionsToArray($dimensions))
                    ->pathOnDisk($media->src, $media->path, $media->legacy_structure)
            ));

        if ($missing->isEmpty()) {
            return;
        }

        RegenerateSizesForMediaFileJob::dispatch($media);
        $regeneratedMediaIds[] = $media->id;

        Log::info('VerifyVehicleProviderMediaJob: triggered size regeneration', [
            'tenant_id' => tenant('id'),
            'media_id' => $media->id,
            'missing_sizes' => $missing->values()->all(),
        ]);

        ApiNotification::query()->create([
            'provider' => 'media-check',
            'reference' => (string) $media->id,
            'processed' => true,
            'data_model' => 'media',
            'data' => [
                'action' => 'regenerate-sizes',
                'media_id' => $media->id,
                'image_provider' => $media->image_provider,
                'path' => $media->path . '/' . $media->src,
                'owner_type' => $use->owner_type,
                'owner_id' => $use->owner_id,
                'missing_sizes' => $missing->values()->all(),
            ],
        ]);
    }

    private function removeOrphanMedia(Media $media, MediaUse $use): void
    {
        $context = [
            'media_id' => $media->id,
            'image_provider' => $media->image_provider,
            'path' => $media->path . '/' . $media->src,
            'owner_type' => $use->owner_type,
            'owner_id' => $use->owner_id,
        ];

        $media->uses()->delete();
        $media->delete();

        Log::info('VerifyVehicleProviderMediaJob: removed media with missing original file', [
            'tenant_id' => tenant('id'),
        ] + $context);

        ApiNotification::query()->create([
            'provider' => 'media-check',
            'reference' => (string) $media->id,
            'processed' => true,
            'data_model' => 'media',
            'data' => ['action' => 'delete-missing-original'] + $context,
        ]);
    }

    private static function dimensionsToArray(string $dimensions): array
    {
        [$width, $height] = explode('x', $dimensions);
        return [
            'width' => (int) $width,
            'height' => $height === 'Auto' ? null : (int) $height,
        ];
    }
}
