<?php

namespace Modules\Vrc\Services\Adapters\Http;

use Illuminate\Support\Facades\Http;
use Modules\Vrc\Services\Adapters\Stub\StubRepairInfoService;
use Modules\Vrc\Services\Contracts\RepairInfoServiceContract;

/**
 * Config-driven HTTP adapter for a licensed ISO 18541 RMI provider
 * (TecRMI / HaynesPro / Autodata, or any REST gateway). It reads provider
 * credentials from config('vrc.rmi') (env-backed) and calls the provider's
 * REST endpoints, mapping their responses into the contract shape.
 *
 * Resilience by design:
 *   • When no base_url/api_key is configured, every call DELEGATES to the
 *     offline stub — so this adapter is always safe to bind, even before a
 *     subscription exists.
 *   • On any transport/HTTP error it falls back to the stub too, so the RMI
 *     console never hard-fails in front of a technician.
 *
 * To go live: set VRC_RMI_BASE_URL + VRC_RMI_API_KEY (and optionally
 * VRC_RMI_PROVIDER), then point the binding in Config/config.php at this class.
 */
class HttpRepairInfoService implements RepairInfoServiceContract
{
    public function __construct(protected StubRepairInfoService $fallback = new StubRepairInfoService())
    {
    }

    public function provider(): string
    {
        return (string) (config('vrc.rmi.provider') ?: 'http');
    }

    public function decodeVin(string $vin): array
    {
        if (! $this->configured()) {
            return $this->fallback->decodeVin($vin);
        }

        try {
            $res = $this->client()->get($this->endpoint('vin_decode', 'vin/decode'), ['vin' => strtoupper(trim($vin))]);
            if ($res->failed()) {
                return $this->fallback->decodeVin($vin);
            }
            $d = (array) $res->json();

            return [
                'status'     => $d['status'] ?? 'ok',
                'vin'        => $d['vin'] ?? strtoupper(trim($vin)),
                'wmi'        => $d['wmi'] ?? substr(strtoupper(trim($vin)), 0, 3),
                'region'     => $d['region'] ?? null,
                'model_year' => $d['model_year'] ?? ($d['year'] ?? null),
                'make'       => $d['make'] ?? null,
                'model'      => $d['model'] ?? null,
                'note'       => 'Decoded by ' . $this->provider() . '.',
            ];
        } catch (\Throwable $e) {
            \Log::warning('[vrc.rmi] decodeVin failed: ' . $e->getMessage());

            return $this->fallback->decodeVin($vin);
        }
    }

    public function lookup(string $useCase, array $params): array
    {
        if (! $this->configured()) {
            return $this->fallback->lookup($useCase, $params);
        }

        try {
            $res = $this->client()->get($this->endpoint('lookup', 'lookup'), array_merge(
                ['use_case' => $useCase],
                array_intersect_key($params, array_flip(['make', 'model', 'year', 'vin', 'query']))
            ));
            if ($res->failed()) {
                return $this->fallback->lookup($useCase, $params);
            }
            $d = (array) $res->json();

            // Accept either a ready 'sections' array or a provider 'items' list.
            $sections = $d['sections'] ?? array_map(
                static fn ($i) => is_array($i) ? ($i['text'] ?? json_encode($i)) : (string) $i,
                (array) ($d['items'] ?? [])
            );

            return [
                'status'   => $d['status'] ?? (empty($sections) ? 'not_found' : 'ok'),
                'title'    => $d['title'] ?? ucfirst($useCase),
                'use_case' => $useCase,
                'sections' => $sections,
                'note'     => 'Source: ' . $this->provider() . ' (licensed RMI).',
            ];
        } catch (\Throwable $e) {
            \Log::warning('[vrc.rmi] lookup failed: ' . $e->getMessage());

            return $this->fallback->lookup($useCase, $params);
        }
    }

    /** True only when both a base URL and an API key are present. */
    protected function configured(): bool
    {
        return ! empty(config('vrc.rmi.base_url')) && ! empty(config('vrc.rmi.api_key'));
    }

    protected function client()
    {
        $key = (string) config('vrc.rmi.api_key');
        $header = (string) (config('vrc.rmi.auth_header') ?: 'Authorization');
        $scheme = (string) (config('vrc.rmi.auth_scheme') ?: 'Bearer');

        return Http::baseUrl(rtrim((string) config('vrc.rmi.base_url'), '/'))
            ->timeout((int) (config('vrc.rmi.timeout') ?: 10))
            ->acceptJson()
            ->withHeaders([$header => trim($scheme . ' ' . $key)]);
    }

    /** Resolve a per-endpoint path override, falling back to a sensible default. */
    protected function endpoint(string $key, string $default): string
    {
        return (string) (config('vrc.rmi.endpoints.' . $key) ?: $default);
    }
}
