<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/veiculo_modelo_base.php';

$baseUrl = 'https://fipe.parallelum.com.br/api/v2';
$token = '';
foreach ($argv as $arg) {
    if (str_starts_with($arg, '--token=')) {
        $token = substr($arg, 8);
    }
}

$brandAliases = [
    'GM - Chevrolet' => 'Chevrolet',
    'VW - VolksWagen' => 'Volkswagen',
    'Kia Motors' => 'Kia',
    'Citroën' => 'Citroen',
    'Caoa Chery/Chery' => 'Caoa Chery',
    'GREAT WALL' => 'GWM',
];

$pdo = db();
$brands = api_get($baseUrl . '/cars/brands', $token);
if (!is_array($brands)) {
    throw new RuntimeException('Resposta de marcas invalida.');
}

$totalBrands = count($brands);
$brandIndex = 0;
$importedBrands = 0;
$importedModels = 0;
$requests = 1;

foreach ($brands as $brand) {
    $brandIndex++;
    if (!is_array($brand)) {
        continue;
    }

    $brandCode = trim((string) ($brand['code'] ?? $brand['codigo'] ?? ''));
    $brandName = trim((string) ($brand['name'] ?? $brand['nome'] ?? ''));
    if ($brandCode === '' || $brandName === '') {
        continue;
    }

    $brandName = $brandAliases[$brandName] ?? $brandName;
    $idMarca = upsert_brand($pdo, $brandName);

    $models = api_get($baseUrl . '/cars/brands/' . rawurlencode($brandCode) . '/models', $token);
    $requests++;
    $models = normalize_list($models);

    $countThisBrand = 0;
    foreach ($models as $model) {
        if (!is_array($model)) {
            continue;
        }

        $modelName = clean_model_name((string) ($model['name'] ?? $model['nome'] ?? $model['model'] ?? $model['modelo'] ?? ''));
        if ($modelName === '') {
            continue;
        }

        upsert_model($pdo, $idMarca, $modelName);
        $importedModels++;
        $countThisBrand++;
    }

    $importedBrands++;
    echo '[' . $brandIndex . '/' . $totalBrands . '] ' . $brandName . ': ' . $countThisBrand . " modelos\n";
    usleep(120000);
}

echo "Concluido: {$importedBrands} marcas, {$importedModels} modelos, {$requests} requisicoes.\n";

function api_get(string $url, string $token): array
{
    $headers = [
        'Accept: application/json',
        'User-Agent: BuloAdminImporter/1.0',
    ];
    if ($token !== '') {
        $headers[] = 'X-Subscription-Token: ' . $token;
    }

    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_CONNECTTIMEOUT => 12,
            CURLOPT_TIMEOUT => 45,
            CURLOPT_HTTPHEADER => $headers,
        ]);
        $body = curl_exec($ch);
        $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($body === false) {
            throw new RuntimeException('Falha HTTP: ' . $error);
        }
    } else {
        $context = stream_context_create([
            'http' => [
                'method' => 'GET',
                'header' => implode("\r\n", $headers),
                'timeout' => 45,
                'ignore_errors' => true,
            ],
        ]);
        $body = @file_get_contents($url, false, $context);
        $status = 0;
        foreach ($http_response_header ?? [] as $header) {
            if (preg_match('/^HTTP\/\S+\s+(\d+)/', $header, $matches)) {
                $status = (int) $matches[1];
                break;
            }
        }
        if ($body === false) {
            throw new RuntimeException('Falha HTTP.');
        }
    }

    if ($status >= 400) {
        throw new RuntimeException('API FIPE respondeu HTTP ' . $status . ' para ' . $url);
    }

    $decoded = json_decode((string) $body, true);
    if (!is_array($decoded)) {
        throw new RuntimeException('JSON invalido para ' . $url);
    }

    return $decoded;
}

function normalize_list(array $payload): array
{
    if ($payload === [] || array_key_exists(0, $payload)) {
        return $payload;
    }

    foreach (['models', 'modelos', 'brands', 'marcas', 'data'] as $key) {
        if (isset($payload[$key]) && is_array($payload[$key])) {
            return normalize_list($payload[$key]);
        }
    }

    return [];
}

function upsert_brand(PDO $pdo, string $name): int
{
    $stmt = $pdo->prepare(
        'INSERT INTO veiculo_marcas_catalogo (nome, ativo)
         VALUES (?, 1)
         ON DUPLICATE KEY UPDATE ativo = 1, id = LAST_INSERT_ID(id)'
    );
    $stmt->execute([$name]);

    return (int) $pdo->lastInsertId();
}

function upsert_model(PDO $pdo, int $brandId, string $name): int
{
    $stmt = $pdo->prepare(
        'INSERT INTO veiculo_modelos_catalogo
         (id_marca, nome, categoria_economica, categoria_plus, categoria_pro, ativo)
         VALUES (?, ?, 1, 0, 0, 1)
         ON DUPLICATE KEY UPDATE ativo = 1, id = LAST_INSERT_ID(id)'
    );
    $stmt->execute([$brandId, $name]);

    return (int) $pdo->lastInsertId();
}

function clean_model_name(string $name): string
{
    $name = preg_replace('/\s+/', ' ', trim($name));
    return veiculo_modelo_base($name ?? '');
}
