<?php

namespace App\VehicleSpec\Services;

use App\VehicleSpec\Config\MotorCheckConfig;
use App\VehicleSpec\Contracts\VehicleSpecData;
use App\VehicleSpec\Contracts\VehicleSpecProvider;
use Mtc\VehicleLookup\Contracts\VehicleStandardEquipmentItem;
use Mtc\VehicleLookup\Contracts\VehicleTechnicalDataItem;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MotorCheck\Services\MotorCheckService;

class MotorCheckSpecProvider implements VehicleSpecProvider
{
    protected array $technicalEquipmentTypes = [
        'Technical',
        'Dimensions',
    ];

    public function __construct(
        protected readonly MotorCheckConfig $config,
    ) {
        Config::set('motor_check.specs_username', $config->clientId());
        Config::set('motor_check.specs_password', $config->clientSecret());
        Config::set('motor_check.country', $config->country());

        Config::set('motor_check.enabled', $config->enabled());
        Config::set('motor_check.allow_local_cache', false);
        Config::set('motor_check.live', true);
        Config::set('motor_check.specs_live', true);
    }

    /**
     * Get specs from API
     *
     * @param Vehicle $vehicle
     * @return VehicleSpecData
     * @throws Exception
     */
    public function getSpec(Vehicle $vehicle): VehicleSpecData
    {
        $spec = new VehicleSpecData();

        if (empty($vehicle->registration_number)) {
            return $spec;
        }

        try {
            $motorCheck = App::make(MotorCheckService::class);
            $specs = $motorCheck->getCarSpecs(str_replace(' ', '', $vehicle->registration_number));

            if (empty($specs->feature_list)) {
                return $spec;
            }

            $spec->standard_equipment = $this->processStandardEquipment($specs->feature_list);

            $spec->technical_data = $this->processTechnicalData($specs->feature_list);
        } catch (Exception $exception) {
            Log::error('Failed to retrieve MotorCheck specs for Vehicle with error: ' .
                $exception->getMessage(), [
                'vehicle' => $vehicle,
            ]);
        }

        return $spec;
    }

    /**
     * Map standard equipment features
     *
     * @param array $features
     * @return Collection
     */
    public function processStandardEquipment(array $features): Collection
    {
        return collect($features)
            ->filter(fn ($feature) => !in_array($feature['type'], $this->technicalEquipmentTypes))
            ->map(fn ($feature) => new VehicleStandardEquipmentItem(
                $feature['name'],
                $feature['value'],
                $feature['type']
            ))
            ->unique('description');
    }

    /**
     * Process technical data response
     *
     * @param array $features
     * @return Collection
     */
    public function processTechnicalData(array $features): Collection
    {
        return collect($features)
            ->filter(fn ($feature) => in_array($feature['type'], $this->technicalEquipmentTypes))
            ->map(fn ($feature) => new VehicleTechnicalDataItem(
                $feature['name'],
                $feature['type'],
                $feature['name'],
                $feature['value']
            ))
            ->unique('description');
    }
}
