<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Mtc\ContentManager\Models\MediaFolder;
use Mtc\MercuryDataModels\CarConfiguratorModel;

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

    /**
     * Create a new job instance.
     */
    public function __construct(private readonly CarConfiguratorModel $configurator, private readonly array $data)
    {
        $this->onQueue('bulk-media');
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        $folder = $this->getImageFolder();
        foreach (['interior', 'exterior'] as $type) {
            $unique_by_flag = collect();
            collect($this->data[$type] ?? [])
                ->map(function ($row) use ($folder, $type) {
                    $this->ensureSelections($row);
                    $images = collect(array_unique($row['images'] ?? []))
                        ->map(fn($image) => strtok($image, '?'))
                        ->unique();

                    $flags = collect($row)
                        ->filter()
                        ->forget('engine') // engine does not change images
                        ->forget('images')
                        ->map(fn($item) => Str::slug(trim($item)))
                        ->prepend($type)
                        ->implode('-');
                    $meta = $images->keyBy(fn($image) => $image)
                        ->map(fn($image) => [
                            'folder_id' => $folder,
                        ]);

                    return [
                        'images' => $images,
                        'flags' => $flags,
                        'meta' => $meta
                    ];
                })
                ->filter(function ($image_data) use ($unique_by_flag) {
                    if ($unique_by_flag->contains($image_data['flags'])) {
                        return false;
                    }
                    $unique_by_flag->prepend($image_data['flags']);
                    return true;
                })
                ->each(fn(array $image_data) => ImportImageUrlList::dispatch(
                    $image_data['images'],
                    $this->configurator,
                    [
                        'doNotRemoveOthers' => true,
                        'updateAssigned' => true,
                        'imageProvider' => 'import',
                        'additionalData' => $image_data['meta'],
                        'meta' => ['flags' => [$image_data['flags'] => true]]
                    ]
                ));
        }
    }

    private function getImageFolder(): int
    {
        $folder = MediaFolder::query()
            ->where('name', $this->configurator->name)
            ->whereHas('parent', fn($parent) => $parent->where('name', 'Car Configurator'))
            ->first();
        if ($folder) {
            return $folder->id;
        }

        $parent = MediaFolder::query()
            ->firstOrCreate([
                'name' => 'Car Configurator',
                'parent_id' => null,
            ]);
        $folder = $parent->children()
            ->create([
                'name' => $this->configurator->name,
            ]);
        return $folder->id;
    }

    private function ensureSelections($row): void
    {
        collect($row)
            ->filter()
            ->forget('images')
            ->each(function ($name, $relationName) {
                $relation = Str::plural($relationName);
                if (in_array($relation, CarConfiguratorModel::$relationship_models)) {
                    $this->configurator->$relation()
                        ->firstOrCreate([
                            'name' => trim($name)
                        ]);
                } else {
                    $section_id = $this->configurator->sections()->where('name', $relation)->first()?->id;
                    $this->configurator->custom()
                        ->firstOrCreate([
                            'section_id' => $section_id,
                            'name' => trim($name),
                        ]);
                }
            });
    }
}
