<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/helpers.php';
require_once __DIR__ . '/../config/corrida_ofertas_helpers.php';

const MOTORISTA_DESTINO_LIMITE_USOS_DIA = 3;

function mf_bool(array $data, string $key, bool $default = false): bool
{
    if (!array_key_exists($key, $data)) {
        return $default;
    }
    $value = $data[$key];
    if (is_bool($value)) {
        return $value;
    }
    if (is_numeric($value)) {
        return (int) $value === 1;
    }
    return in_array(strtolower(trim((string) $value)), ['1', 'true', 'sim', 'yes', 'on'], true);
}

function mf_float(array $data, string $key): ?float
{
    if (!isset($data[$key]) || trim((string) $data[$key]) === '') {
        return null;
    }
    return (float) str_replace(',', '.', (string) $data[$key]);
}

function mf_table_exists(PDO $pdo, string $table): bool
{
    return corrida_table_exists($pdo, $table);
}

function mf_garantir_tabelas(PDO $pdo): void
{
    $pdo->exec(
        'CREATE TABLE IF NOT EXISTS motorista_filtros_corrida (
          id_motorista INT PRIMARY KEY,
          aceita_dinheiro TINYINT(1) NOT NULL DEFAULT 1,
          aceita_economica TINYINT(1) NOT NULL DEFAULT 1,
          aceita_plus TINYINT(1) NOT NULL DEFAULT 1,
          aceita_pro TINYINT(1) NOT NULL DEFAULT 1,
          destino_ativo TINYINT(1) NOT NULL DEFAULT 0,
          destino_lat DECIMAL(10,7) NULL,
          destino_lng DECIMAL(10,7) NULL,
          destino_endereco VARCHAR(255) NULL,
          destino_ativado_em DATETIME NULL,
          destino_usos_data DATE NULL,
          destino_usos INT NOT NULL DEFAULT 0,
          criado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
          atualizado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
          CONSTRAINT fk_motorista_filtros_motorista FOREIGN KEY (id_motorista) REFERENCES usuarios(id) ON DELETE CASCADE,
          INDEX idx_motorista_filtros_destino (destino_ativo, destino_usos_data)
        )'
    );
    $pdo->exec(
        'CREATE TABLE IF NOT EXISTS motorista_destinos_corrida (
          id INT AUTO_INCREMENT PRIMARY KEY,
          id_motorista INT NOT NULL,
          tipo ENUM("favorito", "recente") NOT NULL,
          titulo VARCHAR(80) NULL,
          endereco VARCHAR(255) NOT NULL,
          lat DECIMAL(10,7) NOT NULL,
          lng DECIMAL(10,7) NOT NULL,
          usado_em DATETIME NULL,
          criado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
          atualizado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
          CONSTRAINT fk_motorista_destinos_motorista FOREIGN KEY (id_motorista) REFERENCES usuarios(id) ON DELETE CASCADE,
          INDEX idx_motorista_destinos_motorista (id_motorista, tipo, atualizado_em)
        )'
    );
}

function mf_categorias_disponiveis(PDO $pdo, int $idMotorista): array
{
    $stmt = $pdo->prepare(
        'SELECT v.id,
                COALESCE(vm.categoria_economica, 1) AS economica,
                COALESCE(vm.categoria_plus, 0) AS plus,
                COALESCE(vm.categoria_pro, 0) AS pro
         FROM usuarios u
         INNER JOIN veiculos v
           ON v.id = u.id_veiculo_ativo
          AND v.id_motorista = u.id
          AND v.status = "aprovado"
         LEFT JOIN veiculo_modelos_catalogo vm ON vm.id = v.id_modelo_catalogo
         WHERE u.id = ?
         LIMIT 1'
    );
    $stmt->execute([$idMotorista]);
    $row = $stmt->fetch();
    if (!$row) {
        return ['economica' => false, 'plus' => false, 'pro' => false];
    }

    return [
        'economica' => (int) ($row['economica'] ?? 1) === 1,
        'plus' => (int) ($row['plus'] ?? 0) === 1,
        'pro' => (int) ($row['pro'] ?? 0) === 1,
    ];
}

function mf_filtros(PDO $pdo, int $idMotorista): array
{
    $stmt = $pdo->prepare('SELECT * FROM motorista_filtros_corrida WHERE id_motorista = ? LIMIT 1');
    $stmt->execute([$idMotorista]);
    $row = $stmt->fetch();
    if (!$row) {
        $pdo->prepare('INSERT INTO motorista_filtros_corrida (id_motorista) VALUES (?)')->execute([$idMotorista]);
        $stmt->execute([$idMotorista]);
        $row = $stmt->fetch() ?: [];
    }

    $dataUsos = (string) ($row['destino_usos_data'] ?? '');
    $usosHoje = $dataUsos === date('Y-m-d') ? (int) ($row['destino_usos'] ?? 0) : 0;
    return [
        'aceita_dinheiro' => (int) ($row['aceita_dinheiro'] ?? 1) === 1,
        'aceita_economica' => (int) ($row['aceita_economica'] ?? 1) === 1,
        'aceita_plus' => (int) ($row['aceita_plus'] ?? 1) === 1,
        'aceita_pro' => (int) ($row['aceita_pro'] ?? 1) === 1,
        'destino_ativo' => (int) ($row['destino_ativo'] ?? 0) === 1,
        'destino' => [
            'endereco' => $row['destino_endereco'] ?? '',
            'lat' => $row['destino_lat'] === null ? null : (float) $row['destino_lat'],
            'lng' => $row['destino_lng'] === null ? null : (float) $row['destino_lng'],
        ],
        'destino_usos_hoje' => $usosHoje,
        'destino_usos_limite' => MOTORISTA_DESTINO_LIMITE_USOS_DIA,
    ];
}

function mf_destinos(PDO $pdo, int $idMotorista, string $tipo, int $limit): array
{
    $stmt = $pdo->prepare(
        'SELECT id, tipo, titulo, endereco, lat, lng, usado_em, atualizado_em
         FROM motorista_destinos_corrida
         WHERE id_motorista = ? AND tipo = ?
         ORDER BY atualizado_em DESC, id DESC
         LIMIT ' . max(1, min(10, $limit))
    );
    $stmt->execute([$idMotorista, $tipo]);

    return array_map(static function (array $row): array {
        return [
            'id' => (int) $row['id'],
            'tipo' => $row['tipo'],
            'titulo' => $row['titulo'] ?? '',
            'endereco' => $row['endereco'] ?? '',
            'lat' => (float) $row['lat'],
            'lng' => (float) $row['lng'],
            'usado_em' => $row['usado_em'],
            'atualizado_em' => $row['atualizado_em'],
        ];
    }, $stmt->fetchAll());
}

function mf_salvar_destino(PDO $pdo, int $idMotorista, array $data, string $tipo): void
{
    if (!in_array($tipo, ['favorito', 'recente'], true)) {
        json_fail('Tipo de destino invalido.');
    }

    $endereco = trim((string) ($data['endereco'] ?? ''));
    $lat = mf_float($data, 'lat');
    $lng = mf_float($data, 'lng');
    if ($endereco === '' || $lat === null || $lng === null) {
        json_fail('Endereco do destino incompleto.');
    }

    $titulo = trim((string) ($data['titulo'] ?? ''));
    $delete = $pdo->prepare(
        'DELETE FROM motorista_destinos_corrida
         WHERE id_motorista = ? AND tipo = ? AND endereco = ?'
    );
    $delete->execute([$idMotorista, $tipo, $endereco]);

    $insert = $pdo->prepare(
        'INSERT INTO motorista_destinos_corrida (id_motorista, tipo, titulo, endereco, lat, lng, usado_em)
         VALUES (?, ?, ?, ?, ?, ?, NOW())'
    );
    $insert->execute([$idMotorista, $tipo, $titulo !== '' ? $titulo : null, $endereco, $lat, $lng]);

    $limit = $tipo === 'favorito' ? 2 : 5;
    $trim = $pdo->prepare(
        'DELETE FROM motorista_destinos_corrida
         WHERE id_motorista = ? AND tipo = ?
           AND id NOT IN (
             SELECT id FROM (
               SELECT id
               FROM motorista_destinos_corrida
               WHERE id_motorista = ? AND tipo = ?
               ORDER BY atualizado_em DESC, id DESC
               LIMIT ' . $limit . '
             ) keep_rows
           )'
    );
    $trim->execute([$idMotorista, $tipo, $idMotorista, $tipo]);
}

function mf_payload(PDO $pdo, int $idMotorista): array
{
    return [
        'filtros' => mf_filtros($pdo, $idMotorista),
        'categorias_disponiveis' => mf_categorias_disponiveis($pdo, $idMotorista),
        'favoritos' => mf_destinos($pdo, $idMotorista, 'favorito', 2),
        'recentes' => mf_destinos($pdo, $idMotorista, 'recente', 5),
    ];
}

$data = input_json();
$idMotorista = isset($_GET['id_motorista']) ? (int) $_GET['id_motorista'] : (int) ($data['id_motorista'] ?? 0);
if ($idMotorista <= 0) {
    json_fail('Motorista nao informado.');
}

try {
    $pdo = db();
    mf_garantir_tabelas($pdo);

    $userStmt = $pdo->prepare('SELECT id, tipo FROM usuarios WHERE id = ? LIMIT 1');
    $userStmt->execute([$idMotorista]);
    $user = $userStmt->fetch();
    if (!$user || (string) ($user['tipo'] ?? '') !== 'motorista') {
        json_fail('Motorista nao encontrado.', 404);
    }

    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        json_ok(mf_payload($pdo, $idMotorista));
    }

    $acao = trim((string) ($data['acao'] ?? 'salvar_filtros'));
    if ($acao === 'salvar_destino') {
        mf_salvar_destino($pdo, $idMotorista, $data, trim((string) ($data['tipo'] ?? 'recente')));
        json_ok(mf_payload($pdo, $idMotorista));
    }

    if ($acao === 'remover_destino') {
        $idDestino = (int) ($data['id_destino'] ?? 0);
        if ($idDestino <= 0) {
            json_fail('Destino nao informado.');
        }
        $stmt = $pdo->prepare('DELETE FROM motorista_destinos_corrida WHERE id = ? AND id_motorista = ?');
        $stmt->execute([$idDestino, $idMotorista]);
        json_ok(mf_payload($pdo, $idMotorista));
    }

    $disponiveis = mf_categorias_disponiveis($pdo, $idMotorista);
    $aceitaDinheiro = mf_bool($data, 'aceita_dinheiro', true);
    $aceitaEconomica = $disponiveis['economica'] && mf_bool($data, 'aceita_economica', true);
    $aceitaPlus = $disponiveis['plus'] && mf_bool($data, 'aceita_plus', false);
    $aceitaPro = $disponiveis['pro'] && mf_bool($data, 'aceita_pro', false);
    if (!$aceitaEconomica && !$aceitaPlus && !$aceitaPro) {
        json_fail('Selecione pelo menos um tipo de corrida.');
    }

    $destinoAtivo = mf_bool($data, 'destino_ativo', false);
    $destinoEndereco = trim((string) ($data['destino_endereco'] ?? ''));
    $destinoLat = mf_float($data, 'destino_lat');
    $destinoLng = mf_float($data, 'destino_lng');
    if ($destinoAtivo && ($destinoEndereco === '' || $destinoLat === null || $destinoLng === null)) {
        json_fail('Escolha um destino para ativar o modo destino.');
    }

    $atualStmt = $pdo->prepare('SELECT * FROM motorista_filtros_corrida WHERE id_motorista = ? LIMIT 1');
    $atualStmt->execute([$idMotorista]);
    $atual = $atualStmt->fetch() ?: [];
    $usosData = (string) ($atual['destino_usos_data'] ?? '');
    $usos = $usosData === date('Y-m-d') ? (int) ($atual['destino_usos'] ?? 0) : 0;
    $incrementaUso = false;
    if ($destinoAtivo) {
        $antesAtivo = (int) ($atual['destino_ativo'] ?? 0) === 1;
        $antesLat = $atual['destino_lat'] === null ? null : (float) $atual['destino_lat'];
        $antesLng = $atual['destino_lng'] === null ? null : (float) $atual['destino_lng'];
        $mesmoDestino = $antesLat !== null
            && $antesLng !== null
            && abs($antesLat - (float) $destinoLat) < 0.00001
            && abs($antesLng - (float) $destinoLng) < 0.00001;
        $incrementaUso = !$antesAtivo || !$mesmoDestino;
        if ($incrementaUso && $usos >= MOTORISTA_DESTINO_LIMITE_USOS_DIA) {
            json_fail('Limite diario do modo destino atingido.');
        }
    }

    if ($incrementaUso) {
        $usos++;
    }

    $stmt = $pdo->prepare(
        'INSERT INTO motorista_filtros_corrida
          (id_motorista, aceita_dinheiro, aceita_economica, aceita_plus, aceita_pro,
           destino_ativo, destino_lat, destino_lng, destino_endereco, destino_ativado_em,
           destino_usos_data, destino_usos)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, IF(? = 1, NOW(), NULL), CURDATE(), ?)
         ON DUPLICATE KEY UPDATE
           aceita_dinheiro = VALUES(aceita_dinheiro),
           aceita_economica = VALUES(aceita_economica),
           aceita_plus = VALUES(aceita_plus),
           aceita_pro = VALUES(aceita_pro),
           destino_ativo = VALUES(destino_ativo),
           destino_lat = VALUES(destino_lat),
           destino_lng = VALUES(destino_lng),
           destino_endereco = VALUES(destino_endereco),
           destino_ativado_em = CASE
             WHEN VALUES(destino_ativo) = 1 AND (destino_ativo = 0 OR destino_lat <> VALUES(destino_lat) OR destino_lng <> VALUES(destino_lng))
             THEN NOW()
             WHEN VALUES(destino_ativo) = 0 THEN NULL
             ELSE destino_ativado_em
           END,
           destino_usos_data = CURDATE(),
           destino_usos = VALUES(destino_usos)'
    );
    $stmt->execute([
        $idMotorista,
        $aceitaDinheiro ? 1 : 0,
        $aceitaEconomica ? 1 : 0,
        $aceitaPlus ? 1 : 0,
        $aceitaPro ? 1 : 0,
        $destinoAtivo ? 1 : 0,
        $destinoAtivo ? $destinoLat : null,
        $destinoAtivo ? $destinoLng : null,
        $destinoAtivo ? $destinoEndereco : null,
        $destinoAtivo ? 1 : 0,
        $usos,
    ]);

    if ($destinoAtivo) {
        mf_salvar_destino($pdo, $idMotorista, [
            'endereco' => $destinoEndereco,
            'lat' => $destinoLat,
            'lng' => $destinoLng,
        ], 'recente');
    }

    json_ok(mf_payload($pdo, $idMotorista));
} catch (Throwable $e) {
    json_fail('Erro ao salvar filtros de corrida.', 500, ['error' => $e->getMessage()]);
}
