<?php

namespace App\Modules\Valuation;

use Carbon\Carbon;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Mtc\VehicleValuation\AutoTrader as BaseAutoTrader;
use Mtc\VehicleValuation\Contracts\ValuationResponse;
use Mtc\VehicleValuation\Exceptions\ValuationRequestFailed;

class AutoTrader extends BaseAutoTrader
{
    /**
     * The AutoTrader condition ratings the customer can declare, keyed by the
     * lower-cased cosmetic condition the frontend sends.
     *
     * @var array<string, string>
     */
    private const CONDITION_RATINGS = [
        'excellent' => 'Excellent',
        'great' => 'Great',
        'good' => 'Good',
        'fair' => 'Fair',
        'poor' => 'Poor',
    ];

    /**
     * The response column that carries the value for each price tier (see
     * ConditionPriceTier).
     *
     * @var array<string, string>
     */
    private const TIER_COLUMNS = [
        ConditionPriceTier::TIER_CLEAN => 'cleanPrice',
        ConditionPriceTier::TIER_AVERAGE => 'averagePrice',
        ConditionPriceTier::TIER_BELOW => 'belowPrice',
    ];

    /**
     * When the customer has declared a known cosmetic condition we request that
     * exact AutoTrader rating and store only its value, so a single call is
     * made. With no (or an unrecognised) condition we defer to the parent's
     * multi-condition behaviour so every tier is available.
     */
    #[\Override]
    public function getValuation(
        string $registration,
        int $mileage,
        ?string $variant = null,
        ?string $cosmetic_condition = null,
        ?array $data = null,
    ): ValuationResponse {
        $rating = self::CONDITION_RATINGS[strtolower($cosmetic_condition ?? '')] ?? null;
        $tier = ConditionPriceTier::fromCondition($cosmetic_condition);
        if ($rating === null || $tier === null) {
            return parent::getValuation($registration, $mileage, $variant, $cosmetic_condition, $data);
        }

        return $this->getConditionValuation(
            $registration,
            $mileage,
            $cosmetic_condition,
            $rating,
            self::TIER_COLUMNS[$tier],
        );
    }

    private function getConditionValuation(
        string $registration,
        int $mileage,
        string $cosmetic_condition,
        string $rating,
        string $column,
    ): ValuationResponse {
        $vehicleData = $this->getVehicleData($registration);

        $response = Http::withHeaders($this->headers())
            ->post($this->endpoint('valuations?advertiserId=' . $this->config->merchantId()), [
                'vehicle' => [
                    'derivativeId' => $vehicleData['derivativeId'],
                    'firstRegistrationDate' => $vehicleData['firstRegistrationDate'],
                    'odometerReadingMiles' => $mileage,
                ],
                'conditionRating' => $rating,
            ]);

        $payload = $response instanceof Response ? $response->json('valuations') : null;
        if (!$response instanceof Response || $response->failed() || empty($payload)) {
            Log::warning('AutoTrader Valuation Request failed', [
                'message' => $response instanceof Response ? $response->body() : 'no response',
                'status' => $response instanceof Response ? $response->status() : 0,
                'registration' => $registration,
                'mileage' => $mileage,
                'conditionRating' => $rating,
            ]);
            throw new ValuationRequestFailed('Failed to get valuation details from AutoTrader.');
        }

        $prices = [
            'retailPrice' => null,
            'averagePrice' => null,
            'cleanPrice' => null,
            'belowPrice' => null,
        ];
        $prices[$column] = $this->amount($payload['partExchange'] ?? null);

        return new ValuationResponse(
            provider: 'auto-trader',
            registration: $registration,
            mileage: $mileage,
            cosmetic_condition: $cosmetic_condition,
            vehicleType: $vehicleData['vehicleType'] ?? '',
            retailPrice: $prices['retailPrice'],
            averagePrice: $prices['averagePrice'],
            cleanPrice: $prices['cleanPrice'],
            belowPrice: $prices['belowPrice'],
            make: $vehicleData['make'] ?? '',
            model: $vehicleData['model'] ?? '',
            derivative: $vehicleData['derivative'] ?? '',
            fuelType: $vehicleData['fuelType'] ?? '',
            engineSize: $vehicleData['engineSize'] ?? '',
            bodyType: $vehicleData['bodyType'] ?? '',
            transmission: $vehicleData['transmission'] ?? '',
            registrationDate: Carbon::createFromFormat('Y-m-d', $vehicleData['firstRegistrationDate']),
            colour: $vehicleData['colour'] ?? '',
            data: [
                'derivativeId' => $vehicleData['derivativeId'],
                'VIN' => $vehicleData['vin'],
                'previous_owners' => $vehicleData['owners'],
                'firstRegistrationDate' => $vehicleData['firstRegistrationDate'],
                'auto_trader_valuations' => [strtolower($rating) => $payload],
            ],
        );
    }
}
