<?php
declare(strict_types=1);

require_once __DIR__ . '/_bootstrap.php';
admin_require_login();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: configuracoes.php');
    exit;
}

$campos = [
    'preco_base' => 'Economica: valor inicial fixo da corrida',
    'preco_por_km' => 'Economica: valor cobrado por quilômetro',
    'preco_por_minuto' => 'Economica: valor cobrado por minuto estimado',
    'taxa_servico' => 'Economica: taxa fixa adicional da plataforma',
    'valor_minimo' => 'Economica: menor valor permitido para a corrida',
    'plus_preco_base' => 'Plus: valor inicial fixo da corrida',
    'plus_preco_por_km' => 'Plus: valor cobrado por quilômetro',
    'plus_preco_por_minuto' => 'Plus: valor cobrado por minuto estimado',
    'plus_taxa_servico' => 'Plus: taxa fixa adicional da plataforma',
    'plus_valor_minimo' => 'Plus: menor valor permitido para a corrida',
    'pro_preco_base' => 'Pro: valor inicial fixo da corrida',
    'pro_preco_por_km' => 'Pro: valor cobrado por quilômetro',
    'pro_preco_por_minuto' => 'Pro: valor cobrado por minuto estimado',
    'pro_taxa_servico' => 'Pro: taxa fixa adicional da plataforma',
    'pro_valor_minimo' => 'Pro: menor valor permitido para a corrida',
];

function post_money(string $key): float
{
    $raw = str_replace(',', '.', trim((string) ($_POST[$key] ?? '')));
    if ($raw === '' || !is_numeric($raw) || (float) $raw < 0) {
        throw new RuntimeException('Valor inválido para ' . $key);
    }

    return round((float) $raw, 2);
}

function post_decimal_range(string $key, float $min, float $max, float $fallback): float
{
    $raw = str_replace(',', '.', trim((string) ($_POST[$key] ?? '')));
    if ($raw === '') {
        return $fallback;
    }
    if (!is_numeric($raw)) {
        throw new RuntimeException('Valor invalido para ' . $key);
    }

    return round(min($max, max($min, (float) $raw)), 2);
}

function post_int_range(string $key, int $min, int $max, int $fallback): int
{
    $raw = trim((string) ($_POST[$key] ?? ''));
    if ($raw === '') {
        return $fallback;
    }
    if (!ctype_digit($raw)) {
        throw new RuntimeException('Valor invalido para ' . $key);
    }

    return min($max, max($min, (int) $raw));
}

function salvar_regiao_tarifaria(PDO $pdo, string $adminUser): void
{
    if (!tarifas_table_exists($pdo, 'tarifa_regioes')) {
        throw new RuntimeException('Tabela tarifa_regioes ainda não existe. Rode a atualização do banco.');
    }

    if (!tarifas_column_exists($pdo, 'tarifa_regioes', 'dinamica_ativa')) {
        throw new RuntimeException('Campos de preco dinamico ainda nao existem. Rode a atualizacao do banco.');
    }

    $id = (int) ($_POST['id_regiao'] ?? 0);
    $nome = trim((string) ($_POST['nome'] ?? ''));
    if ($nome === '') {
        throw new RuntimeException('Informe o nome da regiao.');
    }

    $pontos = tarifas_decode_geocerca((string) ($_POST['geocerca_json'] ?? ''));
    if (count($pontos) < 3) {
        throw new RuntimeException('Desenhe a geocerca com pelo menos 3 pontos.');
    }

    $categorias = [
        'economica_ativo' => isset($_POST['economica_ativo']) ? 1 : 0,
        'plus_ativo' => isset($_POST['plus_ativo']) ? 1 : 0,
        'pro_ativo' => isset($_POST['pro_ativo']) ? 1 : 0,
    ];
    if (array_sum($categorias) === 0) {
        throw new RuntimeException('Ative pelo menos uma categoria para essa regiao.');
    }

    $latitudes = array_column($pontos, 'lat');
    $longitudes = array_column($pontos, 'lng');
    $centroLat = round(array_sum($latitudes) / count($latitudes), 7);
    $centroLng = round(array_sum($longitudes) / count($longitudes), 7);
    $geocercaJson = json_encode($pontos, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    $dados = [
        'nome' => $nome,
        'ativo' => isset($_POST['ativo']) ? 1 : 0,
        'ordem' => max(0, (int) ($_POST['ordem'] ?? 100)),
        'geocerca_json' => $geocercaJson,
        'centro_lat' => $centroLat,
        'centro_lng' => $centroLng,
        'preco_base' => post_money('preco_base'),
        'preco_por_km' => post_money('preco_por_km'),
        'preco_por_minuto' => post_money('preco_por_minuto'),
        'taxa_servico' => post_money('taxa_servico'),
        'valor_minimo' => post_money('valor_minimo'),
        'plus_preco_base' => post_money('plus_preco_base'),
        'plus_preco_por_km' => post_money('plus_preco_por_km'),
        'plus_preco_por_minuto' => post_money('plus_preco_por_minuto'),
        'plus_taxa_servico' => post_money('plus_taxa_servico'),
        'plus_valor_minimo' => post_money('plus_valor_minimo'),
        'pro_preco_base' => post_money('pro_preco_base'),
        'pro_preco_por_km' => post_money('pro_preco_por_km'),
        'pro_preco_por_minuto' => post_money('pro_preco_por_minuto'),
        'pro_taxa_servico' => post_money('pro_taxa_servico'),
        'pro_valor_minimo' => post_money('pro_valor_minimo'),
        'economica_ativo' => $categorias['economica_ativo'],
        'plus_ativo' => $categorias['plus_ativo'],
        'pro_ativo' => $categorias['pro_ativo'],
        'dinamica_ativa' => isset($_POST['dinamica_ativa']) ? 1 : 0,
        'dinamica_multiplicador_max' => post_decimal_range('dinamica_multiplicador_max', 1.00, 3.00, 1.80),
        'dinamica_sensibilidade' => in_array(($_POST['dinamica_sensibilidade'] ?? 'media'), ['baixa', 'media', 'alta'], true)
            ? (string) $_POST['dinamica_sensibilidade']
            : 'media',
        'dinamica_celula_km' => post_decimal_range('dinamica_celula_km', 0.80, 8.00, 2.00),
        'dinamica_janela_minutos' => post_int_range('dinamica_janela_minutos', 1, 60, 12),
        'admin' => $adminUser,
    ];

    if ($id > 0) {
        $stmt = $pdo->prepare(
            'UPDATE tarifa_regioes
             SET nome = :nome,
                 ativo = :ativo,
                 ordem = :ordem,
                 geocerca_json = :geocerca_json,
                 centro_lat = :centro_lat,
                 centro_lng = :centro_lng,
                 preco_base = :preco_base,
                 preco_por_km = :preco_por_km,
                 preco_por_minuto = :preco_por_minuto,
                 taxa_servico = :taxa_servico,
                 valor_minimo = :valor_minimo,
                 plus_preco_base = :plus_preco_base,
                 plus_preco_por_km = :plus_preco_por_km,
                 plus_preco_por_minuto = :plus_preco_por_minuto,
                 plus_taxa_servico = :plus_taxa_servico,
                 plus_valor_minimo = :plus_valor_minimo,
                 pro_preco_base = :pro_preco_base,
                 pro_preco_por_km = :pro_preco_por_km,
                 pro_preco_por_minuto = :pro_preco_por_minuto,
                 pro_taxa_servico = :pro_taxa_servico,
                 pro_valor_minimo = :pro_valor_minimo,
                 economica_ativo = :economica_ativo,
                 plus_ativo = :plus_ativo,
                 pro_ativo = :pro_ativo,
                 dinamica_ativa = :dinamica_ativa,
                 dinamica_multiplicador_max = :dinamica_multiplicador_max,
                 dinamica_sensibilidade = :dinamica_sensibilidade,
                 dinamica_celula_km = :dinamica_celula_km,
                 dinamica_janela_minutos = :dinamica_janela_minutos,
                 atualizado_por = :admin
             WHERE id = :id'
        );
        $dados['id'] = $id;
        $stmt->execute($dados);
        return;
    }

    $stmt = $pdo->prepare(
        'INSERT INTO tarifa_regioes
         (nome, ativo, ordem, geocerca_json, centro_lat, centro_lng,
          preco_base, preco_por_km, preco_por_minuto, taxa_servico, valor_minimo,
          plus_preco_base, plus_preco_por_km, plus_preco_por_minuto, plus_taxa_servico, plus_valor_minimo,
          pro_preco_base, pro_preco_por_km, pro_preco_por_minuto, pro_taxa_servico, pro_valor_minimo,
          economica_ativo, plus_ativo, pro_ativo,
          dinamica_ativa, dinamica_multiplicador_max, dinamica_sensibilidade, dinamica_celula_km, dinamica_janela_minutos,
          criado_por, atualizado_por)
         VALUES
         (:nome, :ativo, :ordem, :geocerca_json, :centro_lat, :centro_lng,
          :preco_base, :preco_por_km, :preco_por_minuto, :taxa_servico, :valor_minimo,
          :plus_preco_base, :plus_preco_por_km, :plus_preco_por_minuto, :plus_taxa_servico, :plus_valor_minimo,
          :pro_preco_base, :pro_preco_por_km, :pro_preco_por_minuto, :pro_taxa_servico, :pro_valor_minimo,
          :economica_ativo, :plus_ativo, :pro_ativo,
          :dinamica_ativa, :dinamica_multiplicador_max, :dinamica_sensibilidade, :dinamica_celula_km, :dinamica_janela_minutos,
          :criado_por, :atualizado_por)'
    );
    $dados['criado_por'] = $adminUser;
    $dados['atualizado_por'] = $adminUser;
    unset($dados['admin']);
    $stmt->execute($dados);
}

try {
    $pdo = db();
    $pdo->beginTransaction();
    $adminUser = admin_current_user();

    if (($_POST['tipo'] ?? '') === 'regiao') {
        salvar_regiao_tarifaria($pdo, $adminUser);
        $pdo->commit();
        admin_flash('Regiao tarifaria salva com sucesso.');
        header('Location: configuracoes.php');
        exit;
    }

    $stmt = $pdo->prepare(
        'INSERT INTO configuracoes (chave, valor, descricao, atualizado_por)
         VALUES (?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
            valor = VALUES(valor),
            descricao = VALUES(descricao),
            atualizado_por = VALUES(atualizado_por)'
    );
    $stmtAtual = $pdo->prepare('SELECT valor FROM configuracoes WHERE chave = ? LIMIT 1');
    $stmtHistorico = $pdo->prepare(
        'INSERT INTO configuracoes_historico (chave, valor_anterior, valor_novo, alterado_por)
         VALUES (?, ?, ?, ?)'
    );

    foreach ($campos as $chave => $descricao) {
        $valorNovo = post_money($chave);

        $stmtAtual->execute([$chave]);
        $valorAnterior = $stmtAtual->fetchColumn();
        $valorAnterior = $valorAnterior === false ? null : round((float) $valorAnterior, 2);

        $stmt->execute([$chave, $valorNovo, $descricao, $adminUser]);

        if ($valorAnterior === null || $valorAnterior !== $valorNovo) {
            $stmtHistorico->execute([$chave, $valorAnterior, $valorNovo, $adminUser]);
        }
    }

    $pdo->commit();
    admin_flash('Configurações salvas com sucesso.');
} catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    admin_flash('Erro ao salvar configurações: ' . $e->getMessage(), 'error');
}

header('Location: configuracoes.php');
exit;
