<?php

namespace App\Modules\VehicleLabels;

use App\Facades\Settings;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\LabelRule;
use Mtc\MercuryDataModels\Vehicle;

class LabelRepository
{
    public function getAutomationOptions(): array
    {
        return $this->automationOptions()
            ->map(fn($option) => collect($option)->only(['id', 'name']))
            ->toArray();
    }

    public function getVehicleTypeOptions(): array
    {
        return [
            [
                'id' => 'any',
                'name' => 'Any'
            ],
            [
                'id' => 'car',
                'name' => 'Car'
            ],
            [
                'id' => 'lcv',
                'name' => 'LCV'
            ],
            [
                'id' => 'motorcycle',
                'name' => 'Motorcycle'
            ],
        ];
    }

    public function shouldAssign(Vehicle $vehicle, Label $label): bool
    {
        // Safe fallback. Assume applicable if setting does not exist.
        if (($label->data['applies_to_stock_vehicles'] ?? true) == false) {
            return false;
        }

        $exists = $vehicle->labels()->where('label_id', $label->id)->exists();
        $isApplicable = $this->conditionMatches($vehicle, $label->data['assign_when'] ?? null);

        $shouldCheckAdvancedRules = Settings::get('vehicle-labels-advanced-rules-enabled')
            && (
                empty($label->data['assign_when'])
                || $isApplicable
            );

        if ($shouldCheckAdvancedRules) {
            $isApplicable = $this->advancedConditionsMatch($vehicle, $label);
        }

        return !$exists && $isApplicable;
    }

    public function shouldRevoke(Vehicle $vehicle, Label $label): bool
    {
        // Safe fallback. Assume applicable if setting does not exist.
        if (($label->data['applies_to_stock_vehicles'] ?? true) == false) {
            return true;
        }

        $exists = $vehicle->labels()->where('label_id', $label->id)->exists();

        if (!$exists) {
            return true;
        }

        $isApplicable = $this->conditionMatches($vehicle, $label->data['revoke_when'] ?? null);

        if (
            Settings::get('vehicle-labels-advanced-rules-enabled')
            && $isApplicable == false
        ) {
            // if the advanced conditions do not match, the label is eligible for revoking
            $isApplicable = !$this->advancedConditionsMatch($vehicle, $label);
        }

        return $isApplicable;
    }

    private function advancedConditionsMatch(Vehicle $vehicle, Label $label)
    {
        $success = true;
        $vehicle_mileage = Settings::get('automotive-distance_measurement') === 'mi'
            ? $vehicle->odometer_mi
            : $vehicle->odometer_km;
        $vehicle_age = Carbon::now()->diff($vehicle->first_registration_date)->y;

        $label->rules->each(function (LabelRule $rule) use ($vehicle, &$success, $vehicle_age, $vehicle_mileage) {
            if ($rule->value_data_type != 'boolean' && empty($rule->condition_value)) {
                // continue to the next iteration
                return true;
            }

            $success = match ($rule->condition_field) {
                'vehicle_price_min' => $vehicle->price >= $rule->getValue(),
                'vehicle_price_max' => $vehicle->price < $rule->getValue(),
                'vehicle_mpg_min' => $vehicle->mpg >= $rule->getValue(),
                'vehicle_mpg_max' => $vehicle->mpg < $rule->getValue(),
                'vehicle_mileage_min' => $vehicle_mileage >= $rule->getValue(),
                'vehicle_mileage_max' => $vehicle_mileage < $rule->getValue(),
                'vehicle_days_in_stock_min' => $vehicle->daysInStock >= $rule->getValue(),
                'vehicle_days_in_stock_max' => $vehicle->daysInStock < $rule->getValue(),
                'vehicle_age_min' => !empty($vehicle->first_registration_date) && ($vehicle_age >= $rule->getValue()),
                'vehicle_age_max' => !empty($vehicle->first_registration_date) && ($vehicle_age < $rule->getValue()),
                'active_from' => Carbon::now() >= $rule->getValue(),
                'active_to' => Carbon::now() < $rule->getValue(),
                'transmission_id' => $vehicle->transmission_id == $rule->getValue(),
                'fuel_type_id' => $vehicle->fuel_type_id == $rule->getValue(),
                'vehicle_type' => ($rule->getValue() == 'any' || $vehicle->type == $rule->getValue()),
                'vehicle_category' => $vehicle->getCustom('vehicle_category') == $rule->getValue(),
                'vehicle_is_new' => $vehicle->is_new == $rule->getValue(),
                'vrms_included' => in_array($vehicle->vrm_condensed, array_filter($rule->getValue())),
                'vrms_excluded' => !in_array($vehicle->vrm_condensed, array_filter($rule->getValue())),
                'vrm_is_empty' => empty($vehicle->vrm_condensed),
                'make_ids' => in_array($vehicle->make_id, $rule->getValue()),
                'model_ids' => in_array($vehicle->model_id, $rule->getValue()),
                'dealership_ids' => in_array($vehicle->dealership_id, $rule->getValue()),
                default => true, // return true for an unsupported rule
            };

            // returning false will break out of the loop
            return $success;
        });

        return $success;
    }

    private function conditionMatches(Vehicle $vehicle, ?string $param): bool
    {
        $matchedCondition = $this->automationOptions()
            ->filter(fn($condition) => $condition['id'] === $param)
            ->first();

        return $matchedCondition && $matchedCondition['condition']($vehicle);
    }

    private function automationOptions(): Collection
    {
        return collect([
            [
                'id' => 'available_date_in_future',
                'name' => 'Available Date is in future',
                'condition' => fn(Vehicle $vehicle) => $vehicle->available_date > Carbon::now(),
            ],
            [
                'id' => 'available_date_in_past',
                'name' => 'Available Date is in past',
                'condition' => fn(Vehicle $vehicle) => $vehicle->available_date < Carbon::now(),
            ],
            [
                'id' => 'is_reserved',
                'name' => 'Vehicle is reserved',
                'condition' => fn(Vehicle $vehicle) => $vehicle->is_reserved,
            ],
            [
                'id' => 'is_new',
                'name' => 'Vehicle is a new vehicle',
                'condition' => fn(Vehicle $vehicle) => $vehicle->is_new,
            ],
            [
                'id' => 'is_demo',
                'name' => 'Vehicle is an ex-demo vehicle',
                'condition' => fn(Vehicle $vehicle) => $vehicle->is_demo,
            ],
            [
                'id' => 'is_pre_reg',
                'name' => 'Vehicle is a Pre-Reg vehicle',
                'condition' => fn(Vehicle $vehicle) => $vehicle->is_pre_reg,
                'enabled' => Settings::get('vehicles-pre-reg-condition-enabled')
            ],
            [
                'id' => 'has_personalized_number_plate',
                'name' => 'Vehicle has a personalized number plate',
                'condition' => fn(Vehicle $vehicle) => $vehicle->personalized_number_plate,
            ],
            [
                'id' => 'has_reduced_price',
                'name' => 'Vehicle has a reduced(sale) price',
                'condition' => fn(Vehicle $vehicle) => $vehicle->price < $vehicle->original_price
                    && $vehicle->price > 0,
            ],
            [
                'id' => 'just_arrived',
                'name' => 'Just Arrived',
                'condition' => fn(Vehicle $vehicle) => $vehicle->created_at >= Carbon::now()->subDays(
                    Settings::get('vehicle-labels-just-arrived-days')
                ),
            ],
            [
                'id' => 'not_just_arrived',
                'name' => 'Not Just Arrived',
                'condition' => fn(Vehicle $vehicle) => $vehicle->created_at < Carbon::now()->subDays(
                    Settings::get('vehicle-labels-just-arrived-days')
                ),
            ],
        ])->filter(fn($condition) => $condition['enabled'] ?? true);
    }
}
