<?php

namespace App\VehicleSpec\Jobs;

use App\TaxonomyMap;
use App\Traits\MapsTaxonomies;
use App\VehicleSpec\Services\HPICapIdLookupService;
use App\VehicleType;
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\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\Notifications\Facades\Notification;

class VehicleCapIdLookupViaHPI implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;
    use MapsTaxonomies;

    private array $capFields = [
        'cap_id',
        'cap_code'
    ];

    public function __construct(
        protected readonly Vehicle $vehicle,
        protected bool $force = false
    ) {
        $this->onQueue('specs');
    }

    public function handle(): void
    {
        if (!$this->force && !empty($this->vehicle->cap_id)) {
            return;
        }

        $result = $this->hpiCapIdLookupService()->lookup($this->vehicle);

        if (!empty($result['cap_id'])) {
            $this->vehicle->update($this->valuesToUpdate($result));
        } else {
            Notification::addNotification(
                'error',
                'Failed to get CAP ID for vehicle via HPI',
                [
                    $this->vehicle->registration_number,
                ],
                'edit-vehicles',
                "/manage-content/vehicles/edit/{$this->vehicle->id}",
            );
        }

        $this->storeUnmappedTaxonomy($this->vehicle);
    }

    public function failed(?\Throwable $exception): void
    {
        if (Str::contains($exception->getMessage(), 'Operation timed out after')) {
            return;
        }

        Log::error($exception->getMessage(), [
            'tenant' => tenant('id'),
            'vehicle' => $this->vehicle,
            'exception' => $exception,
        ]);
    }

    protected function getProviderName(): string
    {
        return 'hpi';
    }

    protected function getDetailsForTaxonomyMap(array $record): array
    {
        return [
            'tenant_id' => tenant('id'),
            'registration_number' => $this->vehicle?->registration_number ?? '',
            'make' => $record['make_id'] ?? '',
            'model' => $record['model_id'] ?? '',
            'fuel_type' => $record['fuel_type_id'] ?? '',
            'transmission' => $record['transmission_id'] ?? '',
        ];
    }

    private function hpiCapIdLookupService(): HPICapIdLookupService
    {
        return App::make(HPICapIdLookupService::class);
    }

    private function valuesToUpdate(array $result): array
    {
        return collect($result)
            ->filter(fn($value, $field) => in_array($field, $this->capFields, true)
                || $this->columnCanBeUpdated($field))
            ->map(fn($value, $field) => $this->columnAdjustedValue($value, $field, $result))
            ->filter()
            ->toArray();
    }

    private function columnCanBeUpdated($field): bool
    {
        return in_array($field, $this->capFields, true);
    }

    private function columnAdjustedValue($value, string $field, array $result)
    {
        return match ($field) {
            'type' => $value === 'Car' ? VehicleType::CAR->value : VehicleType::LCV->value,
            default => $value,
        };
    }
}
