<?php

namespace App\Services;

use App\Facades\Feature;
use App\Facades\Settings;
use App\Jobs\SendVehicleToAutotrader;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Mtc\MercuryDataModels\ApiNotification;
use Mtc\MercuryDataModels\Vehicle;

class AutoTraderHub
{
    private string $token;

    // When enabled the vehicle send/remove workflow runs in-process (direct to the AutoTrader API)
    // instead of being forwarded to the standalone autotrader microservice.
    private const IN_PROCESS_EXPORT_FEATURE = 'auto-trader-in-process-export';

    public function setToken(?string $token): self
    {
        if ($token) {
            $this->token = $token;
        }
        return $this;
    }

    public function initExport(): string
    {
        $response = Http::withHeaders(['authorization' => $this->getToken(), 'accept' => 'application/json'])
            ->timeout(10)
            ->post($this->endpoint("bulk-export"));

        if ($response->failed()) {
            Log::error('failed to export to AutoTraderHub', [
                tenant('id'),
                $response->body(),
            ]);
            throw new \Exception($response->body());
        }

        return $response->json('reference');
    }

    public function bulkExport(string $reference, Collection $vehicles): bool
    {
        $response = Http::withHeaders(['authorization' => $this->getToken(), 'accept' => 'application/json'])
            ->timeout(10)
            ->post($this->endpoint('bulk-export/' . $reference), [
                'vehicles' => $vehicles->map(fn (Vehicle $vehicle) => $this->mapVehicle($vehicle)),
            ]);

        return $response->successful();
    }

    public function export(Vehicle $vehicle): bool
    {
        if ($this->inProcessExportEnabled()) {
            new SendVehicleToAutotrader($vehicle)->handle();
            return true;
        }

        $response = Http::withHeaders([
            'authorization' => $this->getToken(),
            'accept' => 'application/json'
        ])
            ->timeout(30)
            ->post($this->endpoint('send-vehicle'), [
                'vehicle' => $this->mapVehicle($vehicle),
            ]);

        if ($response->status() > 201) {
            ApiNotification::query()->create([
                'provider' => 'at-hub',
                'data' => $response->json(),
                'data_model' => 'vehicle',
                'reference' => $vehicle->vrm_condensed,
            ]);
        }

        return $response->successful();
    }

    public function removeVehicle(Vehicle $vehicle): bool
    {
        if ($this->inProcessExportEnabled()) {
            new SendVehicleToAutotrader($vehicle, true)->handle();
            return true;
        }

        $response = Http::withHeaders([
            'authorization' => $this->getToken(),
            'accept' => 'application/json'
        ])
            ->timeout(30)
            ->post($this->endpoint('remove-vehicle'), [
                'id' => $vehicle->id,
                'autotrader_id' => $vehicle->auto_trader_id,
            ]);

        if ($response->status() > 201 || empty($response->json('status'))) {
            ApiNotification::query()->create([
                'provider' => 'at-hub',
                'data' => $response->json(),
                'data_model' => 'vehicle',
                'reference' => $vehicle->vrm_condensed,
            ]);
        }

        return !empty($response->json('status'));
    }

    private function inProcessExportEnabled(): bool
    {
        return Feature::isEnabled(self::IN_PROCESS_EXPORT_FEATURE);
    }

    private function endpoint(string $path): string
    {
        return config('services.auto-trader-hub.url') . '/api/' . ltrim($path, '/');
    }

    private function mapVehicle(Vehicle $vehicle): array
    {
        return (new AutoTraderVehicleMapper())->mapVehicle($vehicle);
    }

    private function getToken(): string
    {
        return $this->token;
    }

    public function createSite()
    {
        $response = Http::timeout(5)
            ->withHeaders([
                'X-Auth' => config('services.auto-trader-hub.api_key')
            ])
            ->post($this->endpoint('create-site'), [
                'advertiser_id' => Settings::get('auto-trader-advertiser-id'),
                'name' => tenant()->name,
                'base_url' => config('app.url'),
                'endpoint' => route('tenant.notifications.auto-trader-hub.store', tenant(), false),
                'external_id' => tenant()->id,
            ]);

        if ($response->successful()) {
            $apiToken = $response->json('api_token');
            if ($apiToken) {
                Settings::update('auto-trader-hub-token', $apiToken);
            }
        }
    }

    public function addDealerIds(array $advertiserIds): bool
    {
        $advertiserIds = array_values(array_unique(array_filter(array_map(
            fn ($id) => is_scalar($id) ? trim((string) $id) : '',
            $advertiserIds
        ))));

        if (empty($advertiserIds)) {
            return false;
        }

        $response = Http::timeout(5)
            ->withHeaders([
                'X-Auth' => config('services.auto-trader-hub.api_key'),
                'accept' => 'application/json',
            ])
            ->post($this->endpoint('add-dealer-ids'), [
                'external_id' => tenant()->id,
                'advertiser_ids' => $advertiserIds,
            ]);

        if ($response->failed()) {
            Log::error('failed to add dealer IDs to AutoTraderHub', [
                'tenant' => tenant('id'),
                'advertiser_ids' => $advertiserIds,
                'response' => $response->body(),
            ]);
        }

        return $response->successful();
    }
}
