<?php

namespace App\Modules\VehicleLabels;

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

class LeaseLabelRepository
{
    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(KeyloopLeaseVehicleVariant $vehicle, Label $label): bool
    {
        // Safe fallback. Assume applicable if setting does not exist.
        if (($label->data['applies_to_lease_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('lease-vehicle-labels-advanced-rules-enabled')
            && (
                empty($label->data['assign_when'])
                || $isApplicable
            );

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

        return !$exists && $isApplicable;
    }

    public function shouldRevoke(KeyloopLeaseVehicleVariant $vehicle, Label $label): bool
    {
        // Safe fallback. Assume applicable if setting does not exist.
        if (($label->data['applies_to_lease_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('lease-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(KeyloopLeaseVehicleVariant $vehicle, Label $label)
    {
        $success = true;

        $label->rules->each(function (LabelRule $rule) use ($vehicle, &$success) {

            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_ex_vat_ex_vrt >= $rule->getValue(),
                'vehicle_price_max' => $vehicle->price_ex_vat_ex_vrt < $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()),
                'make_ids' => in_array($vehicle->make_id, $rule->getValue()),
                'model_ids' => in_array($vehicle->model_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(KeyloopLeaseVehicleVariant $vehicle, ?string $param): bool
    {

        $days = Carbon::now()->subDays(
            Settings::get('lease-vehicle-labels-just-arrived-days')
        );

        $matchedCondition = $this->automationOptions()
            ->filter(fn ($condition) => $condition['id'] === $param)
            ->first();

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

    private function automationOptions(): Collection
    {
        return collect([
            [
                'id' => 'just_arrived',
                'name' => 'Just Arrived',
                'condition' => fn (KeyloopLeaseVehicleVariant $vehicle) =>
                    $vehicle->created_at >= Carbon::now()->subDays(
                        Settings::get('lease-vehicle-labels-just-arrived-days')
                    ),
            ],
            [
                'id' => 'not_just_arrived',
                'name' => 'Not Just Arrived',
                'condition' => fn (KeyloopLeaseVehicleVariant $vehicle) =>
                    $vehicle->created_at < Carbon::now()->subDays(
                        Settings::get('lease-vehicle-labels-just-arrived-days')
                    ),
            ],
        ]);
    }
}
