<?php

namespace App\Services;

use App\Facades\Settings;
use App\VehicleType;
use Illuminate\Support\Str;
use Mtc\MercuryDataModels\MediaUse;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleFeature;
use Mtc\MercuryDataModels\VehicleStandardEquipment;

/**
 * Builds the AutoTrader export payloads for a vehicle.
 *
 * `mapVehicle()` produces the intermediate associative array shared by the (legacy) microservice
 * forward path and the in-process send job. `toApiSchema()` converts that intermediate array into
 * the real AutoTrader Stock API request body (ported from the microservice SendVehicleToAutoTrader).
 */
class AutoTraderVehicleMapper
{
    private string $deleteSoldSettingKey = 'automotive-sales-channels-auto-trader-unpublish-sold';
    private string $deleteReservedSettingKey = 'automotive-sales-channels-auto-trader-unpublish-reserved';
    private string $markDeletedAsSoldSettingKey = 'auto-trader-upsert-deleted-mark-sold';
    private string $exportedFieldsSettingKey = 'auto-trader-hub-exported-optional-fields';

    private const NOT_PUBLISHED_LIFECYCLE_STATES = ['SOLD', 'DELETED', 'WASTEBIN'];

    // Fields that Hub requires or that are system/control values — always exported regardless of tenant config.
    private const MANDATORY_EXPORT_FIELDS = [
        'id',
        'advertiser_id',
        'stock_id',
        'condition',
        'registration_number',
        'description',
        'attention_grabber',
        'published',
        'publish_advert',
        'publish_profile',
        'vin',
        'derivative',
        'odometer_mi',
        'type',
        'price',
        'manufacture_year',
        'first_registration',
        'at_disabled',
        'autotraderAdvert',
        'profileAdvert',
        'lifecycleState',
        'actions',
    ];

    public function mapVehicle(Vehicle $vehicle): array
    {
        $payload = [
            'id' => $vehicle->id,
            // We do not want to use fallback to Settings to ensure vehicles go to the correct location
            'advertiser_id' => $vehicle->dealership->data['auto-trader-location-id'] ?? null,
            'stock_id' => $vehicle->auto_trader_id,
            'condition' => $vehicle->is_new ? 'New' : 'Used',
            'registration_number' => $vehicle->registration_number,
            'description' => $vehicle->description,
            'attention_grabber' => Str::limit($vehicle->attention_grabber ?? '', 27),
            'published' => $vehicle->is_published,
            'publish_advert' => $vehicle->autoTraderData?->publish_advert ?? $vehicle->is_published,
            'publish_profile' => $vehicle->autoTraderData?->publish_profile ?? $vehicle->is_published,
            'vin' => $vehicle->vin,
            'make' => $vehicle->make?->name,
            'model' => $vehicle->model?->name,
            'derivative' => $vehicle->derivative,
            'derivative_id' => $vehicle->autoTraderData?->derivative_id,
            'odometer_mi' => $vehicle->odometer_mi ?? 0,
            'type' => $this->getVehicleType($vehicle),
            'trim' => $vehicle->trim,
            'body_type' => $vehicle->bodyStyle?->name,
            'fuel_type' => $vehicle->fuelType?->name,
            'transmission_type' => $vehicle->transmission?->name,
            'drivetrain' => $vehicle->drivetrain?->name,
            'seats' => $vehicle->seats,
            'price' => $vehicle->price ?? 0,
            'rrp_price' => $vehicle->rrp_price,
            'admin_fee' => $vehicle->admin_fee,
            'doors' => $vehicle->door_count,
            'co2' => $vehicle->co2,
            'colour' => $vehicle->colour,
            'vehicle_length' => $vehicle->vehicle_length,
            'manufacture_year' => $vehicle->manufacture_year,
            'first_registration' => $vehicle->first_registration_date,
            'previous_owner_count' => $vehicle->previous_owner_count,
            'engine_size_cc' => $vehicle->engine_size_cc,
            'battery_capacity_kwh' => $vehicle->battery_capacity_kwh,
            'battery_range' => $vehicle->battery_range,
            'features' => $this->getVehicleFeatures($vehicle),
            'images' => $vehicle->mediaUses->map(fn (MediaUse $mediaUse) => [
                'media_id' => $mediaUse->media->id,
                'auto_trader_id' => $mediaUse->media->auto_trader_id,
                'url' => $mediaUse->media->getOriginalUrlAttribute(true),
            ]),
            'video_url' => $vehicle->main_video_url,
            'at_disabled' => $this->getVehicleDisabledCondition($vehicle),
            'autotraderAdvert' => $vehicle->data['autotraderAdvert'] ?? null,
            'profileAdvert' => $vehicle->data['profileAdvert'] ?? null,
            'lifecycleState' => $this->getLifecycleState($vehicle),
            'actions' => [
                'sortImages' => $this->shouldSortImages($vehicle),
            ],
            'exDemo' => $vehicle->is_demo,
            'vat_scheme' => $vehicle->is_vat_qualifying ? "VAT Qualifying" : "Marginal",
        ];

        if ($vehicle->is_vat_qualifying) {
            $payload['vat_status'] = $vehicle->is_vat_applicable ? "Inc VAT" : "Ex VAT";
        }

        return $this->applyExportedFieldsSetting($payload);
    }

    /**
     * Convert the intermediate vehicle array into the AutoTrader Stock API request body.
     *
     * @param array $vehicleDetails Output of mapVehicle()
     * @return array
     */
    public function toApiSchema(array $vehicleDetails): array
    {
        $data = [
            'metadata' => [
                'externalStockId' => (tenant('id') ?: 'WEB') . '_' . ($vehicleDetails['id'] ?? ''),
                'lifecycleState' => $this->lifecycleState($vehicleDetails),
            ],
            'vehicle' => array_filter([
                "ownershipCondition" => $vehicleDetails['condition'] ?? null,
                "vin" => $vehicleDetails['vin'] ?? null,
                "make" => $vehicleDetails['make'] ?? null,
                "model" => $vehicleDetails['model'] ?? null,
                "derivative" => $vehicleDetails['derivative'] ?? null,
                "derivativeId" => $vehicleDetails['derivative_id'] ?? null,
                "vehicleType" => $vehicleDetails['type'] ?? null,
                "trim" => $vehicleDetails['trim'] ?? null,
                "bodyType" => $vehicleDetails['body_type'] ?? null,
                "fuelType" => $vehicleDetails['fuel_type'] ?? null,
                "transmissionType" => $vehicleDetails['transmission_type'] ?? null,
                "drivetrain" => $vehicleDetails['drivetrain'] ?? null,
                "seats" => $vehicleDetails['seats'] ?? null,
                "doors" => $vehicleDetails['doors'] ?? null,
                "co2EmissionGPKM" => $vehicleDetails['co2'] ?? null,
                "engineCapacityCC" => $vehicleDetails['engine_size_cc'] ?? null,
                "owners" => $vehicleDetails['previous_owner_count'] ?? null,
                "colour" => $vehicleDetails['colour'] ?? null,
                "yearOfManufacture" => $vehicleDetails['manufacture_year'] ?? null,
                "lengthMM" => $vehicleDetails['vehicle_length'] ?? null,
                "batteryCapacityKWH" => $vehicleDetails['battery_capacity_kwh'] ?? null,
                "batteryRangeMiles" => $vehicleDetails['battery_range'] ?? null,
                "exDemo" => $vehicleDetails['exDemo'] ?? false,
                "standard" => [
                    "make" => $vehicleDetails['make'] ?? null,
                    "model" => $vehicleDetails['model'] ?? null,
                    "derivative" => $vehicleDetails['derivative'] ?? null,
                    "trim" => $vehicleDetails['trim'] ?? null,
                    "bodyType" => $vehicleDetails['body_type'] ?? null,
                    "fuelType" => $vehicleDetails['fuel_type'] ?? null,
                    "transmissionType" => $vehicleDetails['transmission_type'] ?? null,
                    "drivetrain" => $vehicleDetails['drivetrain'] ?? null,
                    "colour" => $vehicleDetails['colour'] ?? null,
                ],
            ]),
            'adverts' => [
                'vatScheme' => $vehicleDetails['vat_scheme'] ?? null,
                'reservationStatus' => $this->reservationStatus($vehicleDetails),
                'retailAdverts' => [
                    'vatStatus' => $vehicleDetails['vat_status'] ?? null,
                    'suppliedPrice' => [
                        'amountGBP' => $vehicleDetails['price'] ?? null,
                    ],
                    'manufacturerRRP' => [
                        'amountGBP' => $vehicleDetails['rrp_price'] ?? null,
                    ],
                    'admin_fee' => [
                        'amountGBP' => $vehicleDetails['admin_fee'] ?? null,
                    ],
                    'attentionGrabber' => $vehicleDetails['attention_grabber'] ?? null,
                    'description' => isset($vehicleDetails['description'])
                        ? Str::limit($vehicleDetails['description'], 4000, '')
                        : null,
                    'advertiserAdvert' => [
                        'status' => $this->advertStatus('published', $vehicleDetails),
                    ],
                    'autotraderAdvert' => [
                        'status' => $this->advertStatus('publish_advert', $vehicleDetails),
                    ],
                    'profileAdvert' => [
                        'status' => $this->advertStatus('publish_profile', $vehicleDetails),
                    ],
                    'locatorAdvert' => [
                        'status' => $this->advertStatus('locatorAdvert', $vehicleDetails),
                    ],
                    'exportAdvert' => [
                        'status' => $this->advertStatus('exportAdvert', $vehicleDetails),
                    ],
                ],
            ],
            'media' => [
                'images' => collect($vehicleDetails['images'] ?? [])
                    ->pluck('auto_trader_id')
                    ->filter()
                    ->values()
                    ->all(),
                'video' => [
                    'href' => $vehicleDetails['video_url'] ?? null,
                ],
            ],
        ];

        if (!empty($vehicleDetails['registration_number'])) {
            $data['vehicle']['registration'] = str_replace(' ', '', $vehicleDetails['registration_number']);
        } else {
            $data['vehicle']['registration'] = null;
            $data['vehicle']['plate'] = null;
        }

        $data['vehicle']['odometerReadingMiles'] = $vehicleDetails['odometer_mi'] ?? 0;
        $data['vehicle']['firstRegistrationDate'] = $vehicleDetails['first_registration'] ?? null;
        $data['vehicle']['dateOfRegistration'] = $vehicleDetails['first_registration'] ?? null;

        if (array_key_exists('features', $vehicleDetails) && is_array($vehicleDetails['features'])) {
            $data['features'] = $vehicleDetails['features'];
        }

        return $data;
    }

    private function advertStatus(string $key, array $vehicleDetails): ?string
    {
        if (in_array($this->lifecycleState($vehicleDetails), self::NOT_PUBLISHED_LIFECYCLE_STATES, true)) {
            return 'NOT_PUBLISHED';
        }

        if ($key === 'published') {
            return ($vehicleDetails['published'] ?? false) ? 'PUBLISHED' : 'NOT_PUBLISHED';
        }

        if (!empty($vehicleDetails['at_disabled'])) {
            return 'NOT_PUBLISHED';
        }

        return isset($vehicleDetails[$key])
            ? ($vehicleDetails[$key] ? 'PUBLISHED' : 'NOT_PUBLISHED')
            : (($vehicleDetails['published'] ?? false) ? 'PUBLISHED' : 'NOT_PUBLISHED');
    }

    private function reservationStatus(array $vehicleDetails): ?string
    {
        return $this->lifecycleState($vehicleDetails) === 'SALE_IN_PROGRESS' ? 'Reserved' : null;
    }

    private function lifecycleState(array $vehicleDetails): ?string
    {
        return $vehicleDetails['lifecycleState'] ?? null;
    }

    private function applyExportedFieldsSetting(array $payload): array
    {
        $allowedOptional = Settings::get($this->exportedFieldsSettingKey);

        if (!is_array($allowedOptional) || empty($allowedOptional)) {
            return $payload;
        }

        $allowed = array_merge(self::MANDATORY_EXPORT_FIELDS, $allowedOptional);

        return array_intersect_key($payload, array_flip($allowed));
    }

    private function getVehicleFeatures(Vehicle $vehicle): array
    {
        $equipmentData = $vehicle->equipment->map(fn (VehicleStandardEquipment $equipment) => [
            'name' => $equipment->description,
            'type' => $equipment->type,
            'category' => $equipment->category,
        ])->toArray();

        $featuresData = $vehicle->features->map(fn (VehicleFeature $feature) => [
            'name' => $feature->name,
            'type' => $feature->category,
        ])->toArray();

        return array_merge($equipmentData, $featuresData);
    }

    private function getLifecycleState(Vehicle $vehicle): string
    {
        if ($vehicle->deleted_at) {
            if (Settings::get($this->markDeletedAsSoldSettingKey, false) ?? false) {
                return 'SOLD';
            }
            return 'DELETED';
        }

        if (
            ((Settings::get($this->deleteSoldSettingKey, false) ?? false) && $vehicle->is_sold) ||
            ((Settings::get($this->deleteReservedSettingKey, false) ?? false) && $vehicle->is_reserved)
        ) {
            return 'DELETED';
        }

        if ($vehicle->is_sold) {
            return 'SOLD';
        }

        if ($vehicle->is_reserved) {
            return 'SALE_IN_PROGRESS';
        }

        return 'FORECOURT';
    }

    private function shouldSortImages(Vehicle $vehicle): bool
    {
        return Settings::get('auto-trader-upsert-sort-images', false) ?? false;
    }

    private function getVehicleDisabledCondition(Vehicle $vehicle): bool
    {
        if (!$vehicle->is_published) {
            return true;
        }

        if (Settings::get('automotive-sales-channels-auto-trader-unpublish-demo') && $vehicle->is_demo) {
            return true;
        }

        if (Settings::get('automotive-sales-channels-auto-trader-unpublish-reserved') && $vehicle->is_reserved) {
            return true;
        }

        if (
            Settings::get('automotive-sales-channels-auto-trader-unpublish-no-images')
            && $vehicle->mediaUses->count() === 0
        ) {
            return true;
        }

        return false;
    }

    private function getVehicleType(Vehicle $vehicle): string
    {
        if ($vehicle->type === VehicleType::CAR->value) {
            return 'Car';
        }

        if ($vehicle->type === VehicleType::MOTORCYCLE->value) {
            return 'Bike';
        }

        return 'Van';
    }
}
