<?php

namespace App\VehicleSpec\Services;

use App\Master\Models\CapVehicle;
use Mtc\MercuryDataModels\VehicleType;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\Vehicle;

class CapVehicleLookupService
{
    public function lookup(Vehicle $vehicle): ?array
    {
        $registrationYear = $this->getRegistrationYear($vehicle);

        $candidates = $this->findCandidates($vehicle, $this->normalizeType($vehicle->type));

        if ($candidates->isEmpty()) {
            return null;
        }

        if ($registrationYear) {
            $filtered = $candidates->filter(fn (CapVehicle $cap) => $this->isActiveInYear($cap, $registrationYear));

            if ($filtered->isNotEmpty()) {
                $candidates = $filtered;
            }
        }

        $bestMatch = $this->selectBestMatch($candidates, $vehicle);

        if (!$bestMatch) {
            return null;
        }

        return [
            'cap_id' => $bestMatch->cap_id,
            'cap_code' => $bestMatch->cap_code,
            'type' => $bestMatch->type === VehicleType::CAR->value ? 'Car' : 'LCV',
        ];
    }

    protected function findCandidates(Vehicle $vehicle, string $vehicleType): Collection
    {
        $makeName = $this->normalizeName($vehicle->master_make_name ?? $vehicle->make ?? '');
        $modelName = $this->normalizeName($vehicle->master_model_name ?? $vehicle->model ?? '');

        if (empty($makeName) || empty($modelName)) {
            return collect();
        }

        $query = CapVehicle::query()
            ->where('type', $vehicleType);

        $exactMakeMatch = $query->clone()
            ->whereRaw('LOWER(manufacturer) = ?', [strtolower($makeName)])
            ->get();

        if ($exactMakeMatch->isEmpty()) {
            $query->where('manufacturer', 'like', '%' . $makeName . '%');
        } else {
            $query->whereRaw('LOWER(manufacturer) = ?', [strtolower($makeName)]);
        }

        return $query
            ->where(function ($q) use ($modelName) {
                $q->whereRaw('LOWER(short_model) = ?', [strtolower($modelName)])
                    ->orWhereRaw('LOWER(model) = ?', [strtolower($modelName)])
                    ->orWhere('short_model', 'like', '%' . $modelName . '%')
                    ->orWhere('model', 'like', '%' . $modelName . '%');
            })
            ->limit(100)
            ->get();
    }

    protected function selectBestMatch(Collection $candidates, Vehicle $vehicle): ?CapVehicle
    {
        if ($candidates->isEmpty()) {
            return null;
        }

        $modelName = $this->normalizeName($vehicle->master_model_name ?? $vehicle->model ?? '');
        $derivative = $this->normalizeName($vehicle->derivative ?? '');

        $scored = $candidates->map(function (CapVehicle $cap) use ($modelName, $derivative) {
            $score = 0;

            if (strtolower($cap->short_model) === strtolower($modelName)) {
                $score += 10;
            } elseif (strtolower($cap->model) === strtolower($modelName)) {
                $score += 8;
            }

            if (!empty($derivative) && !empty($cap->derivative)) {
                $capDerivative = $this->normalizeName($cap->derivative);
                $capShortDerivative = $this->normalizeName($cap->short_derivative ?? '');

                if ($capDerivative === $derivative || $capShortDerivative === $derivative) {
                    $score += 5;
                } elseif (str_contains(strtolower($capDerivative), strtolower($derivative))) {
                    $score += 3;
                } elseif (str_contains(strtolower($derivative), strtolower($capDerivative))) {
                    $score += 2;
                }
            }

            if ($cap->available_new_vehicle) {
                $score += 1;
            }

            return ['cap' => $cap, 'score' => $score];
        });

        $best = $scored->sortByDesc('score')->first();

        return $best['cap'] ?? null;
    }

    protected function getRegistrationYear(Vehicle $vehicle): ?int
    {
        if ($vehicle->first_registration_date) {
            return (int) $vehicle->first_registration_date->year;
        }

        if ($vehicle->manufacture_year) {
            return (int) $vehicle->manufacture_year;
        }

        return null;
    }

    protected function isActiveInYear(CapVehicle $cap, int $year): bool
    {
        if ($cap->model_introduced && $cap->model_introduced > $year) {
            return false;
        }

        if ($cap->model_discontinued && $cap->model_discontinued < $year) {
            return false;
        }

        if ($cap->derivative_introduced_year && $cap->derivative_introduced_year > $year) {
            return false;
        }

        if ($cap->derivative_discontinued_year && $cap->derivative_discontinued_year < $year) {
            return false;
        }

        return true;
    }

    protected function normalizeType(string $type): string
    {
        return match (strtolower($type)) {
            'van' => VehicleType::LCV->value,
            default => $type,
        };
    }

    protected function normalizeName(string $name): string
    {
        return trim(preg_replace('/\s+/', ' ', $name));
    }
}
