<?php

namespace App\Controllers;

use App\Core\Database;
use App\Core\View;
use App\Repositories\MesasRepository;

class MesasController
{
    private function repo(): MesasRepository
    {
        return new MesasRepository(Database::conectar());
    }

    private function config(): array
    {
        $path = dirname(__DIR__, 2) . '/config/database.php';
        return file_exists($path) ? (require $path) : [];
    }

    private function guardaConexao(): void
    {
        if (!Database::estaConfigurado()) { header('Location: /configurar'); exit; }
    }

    // ── Filtros SEM consulta ao banco — só session + GET ─────────────────────
    // Usado para render do shell: TTFB < 10ms, sem conexão Firebird.
    private function filtrosSemDB(): array
    {
        $hoje    = date('Y-m-d');
        $sessAno = isset($_SESSION['filtro_ano']) ? (int)$_SESSION['filtro_ano'] : null;
        $sessMes = isset($_SESSION['filtro_mes']) && (int)$_SESSION['filtro_mes'] > 0
                   ? (int)$_SESSION['filtro_mes'] : null;

        if ($sessAno && $sessMes) {
            $defaultIni = sprintf('%04d-%02d-01', $sessAno, $sessMes);
            $fimDoMes   = date('Y-m-t', strtotime($defaultIni));
            $defaultFim = min($fimDoMes, $hoje);
            if ($defaultIni > $hoje) { $defaultIni = $defaultFim = $hoje; }
        } elseif ($sessAno) {
            $defaultIni = sprintf('%04d-01-01', $sessAno);
            $defaultFim = min(sprintf('%04d-12-31', $sessAno), $hoje);
        } else {
            $defaultIni = date('Y-m-d', strtotime('-29 days'));
            $defaultFim = $hoje;
        }

        $dataIni = $_GET['data_ini'] ?? $defaultIni;
        $dataFim = $_GET['data_fim'] ?? $defaultFim;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = $defaultIni;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataFim))  $dataFim = $defaultFim;
        if ($dataFim < $dataIni) $dataFim = $dataIni;

        $anoSel   = (int)substr($dataIni, 0, 4);
        $anoAtual = (int)date('Y');
        // Anos estáticos (últimos 5) — API retorna anos reais e JS atualiza as abas
        $anos = range($anoAtual, max(2020, $anoAtual - 4));

        return compact('dataIni', 'dataFim', 'anos', 'anoSel');
    }

    // ── API helper: parse e valida datas do GET ───────────────────────────────
    private function parseDatas(string $ultimaFallback): array
    {
        $dataIni = $_GET['data_ini'] ?? date('Y-m-d', strtotime($ultimaFallback . ' -29 days'));
        $dataFim = $_GET['data_fim'] ?? $ultimaFallback;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = date('Y-m-d', strtotime($ultimaFallback . ' -29 days'));
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataFim))  $dataFim = $ultimaFallback;
        if ($dataFim < $dataIni) $dataFim = $dataIni;
        return [$dataIni, $dataFim];
    }

    // ════════════════════════════════════════════════════════════════════════
    //  PÁGINAS — shell instantâneo, sem queries no render
    // ════════════════════════════════════════════════════════════════════════

    public function monitor(): void
    {
        $this->guardaConexao();
        $config  = $this->config();

        View::render('mesas/monitor', [
            'titulo'   => 'Monitor de Mesas — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function historico(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();

        View::render('mesas/historico', [
            'titulo'   => 'Histórico de Mesas — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function porGarcom(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        // Por garçom defaults to 90-day window
        if (!isset($_GET['data_ini'])) {
            $filtros['dataIni'] = date('Y-m-d', strtotime($filtros['dataFim'] . ' -89 days'));
        }

        View::render('mesas/por-garcom', [
            'titulo'   => 'Mesas por Garçom — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function tempoMedio(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();

        View::render('mesas/tempo-medio', [
            'titulo'   => 'Tempo Médio de Mesa — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    // ════════════════════════════════════════════════════════════════════════
    //  APIs JSON — dados carregados pelo browser após o shell aparecer
    // ════════════════════════════════════════════════════════════════════════

    /** GET /api/mesas/kpis?data_ini=&data_fim= */
    public function kpisApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $kpis = $repo->kpis($dataIni, $dataFim);
            echo json_encode([
                'kpis'       => $kpis,
                'ultimaData' => $ultima,
                'dataIni'    => $dataIni,
                'dataFim'    => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/monitor */
    public function monitorApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo    = $this->repo();
            $abertas = $repo->monitor();
            $itens   = $repo->itensMesasAbertas();
            echo json_encode([
                'abertas' => $abertas,
                'itens'   => $itens,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/historico?data_ini=&data_fim= */
    public function historicoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $kpis   = $repo->kpis($dataIni, $dataFim);
            $linhas = $repo->historico($dataIni, $dataFim);
            echo json_encode([
                'kpis'    => $kpis,
                'linhas'  => $linhas,
                'dataIni' => $dataIni,
                'dataFim' => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/por-garcom?data_ini=&data_fim= */
    public function porGarcomApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            // Default: 90 days
            $dataIni = $_GET['data_ini'] ?? date('Y-m-d', strtotime($ultima . ' -89 days'));
            $dataFim = $_GET['data_fim'] ?? $ultima;
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = date('Y-m-d', strtotime($ultima . ' -89 days'));
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataFim))  $dataFim = $ultima;
            if ($dataFim < $dataIni) $dataFim = $dataIni;
            $linhas = $repo->porGarcom($dataIni, $dataFim);
            echo json_encode([
                'linhas'  => $linhas,
                'dataIni' => $dataIni,
                'dataFim' => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/tempo-medio?data_ini=&data_fim= */
    public function tempoMedioApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $raw    = $repo->tempoMedio($dataIni, $dataFim);
            // Calcula tempo em minutos via PHP
            $linhas = [];
            foreach ($raw as $r) {
                $ini = $r['HORA_ABERTURA'] ?? '00:00';
                $fim = $r['HORA_FECHAMENTO'] ?? '00:00';
                if (strlen($ini) >= 5 && strlen($fim) >= 5) {
                    [$hIni, $mIni] = explode(':', substr($ini, 0, 5));
                    [$hFim, $mFim] = explode(':', substr($fim, 0, 5));
                    $minutos = ((int)$hFim * 60 + (int)$mFim) - ((int)$hIni * 60 + (int)$mIni);
                    if ($minutos < 0) $minutos += 1440;
                    $r['MINUTOS'] = $minutos;
                } else {
                    $r['MINUTOS'] = 0;
                }
                $linhas[] = $r;
            }
            $mediaMin = count($linhas) > 0
                ? array_sum(array_column($linhas, 'MINUTOS')) / count($linhas)
                : 0;
            echo json_encode([
                'linhas'   => $linhas,
                'mediaMin' => round($mediaMin),
                'dataIni'  => $dataIni,
                'dataFim'  => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  COMANDAS POR GARÇOM — tela interativa de drill-down (v1.4.21+)
    //  Depto de Engenharia e Automação - Master Automação - Autor: Derlivon Silva
    // ════════════════════════════════════════════════════════════════════════

    /** GET /mesas/comandas-por-garcom — página shell */
    public function comandasPorGarcom(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        if (!isset($_GET['data_ini'])) {
            $filtros['dataIni'] = date('Y-m-d', strtotime($filtros['dataFim'] . ' -29 days'));
        }

        View::render('mesas/comandas-por-garcom', [
            'titulo'   => 'Comandas por Garçom — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    /** GET /api/mesas/garcons — lista pra popular o select */
    public function garconsApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo    = $this->repo();
            $garcons = $repo->listarGarcons();
            echo json_encode(['garcons' => $garcons], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/comandas-garcom?cod_garcom=&data_ini=&data_fim= */
    public function comandasGarcomApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $codGarcom = isset($_GET['cod_garcom']) ? (int)$_GET['cod_garcom'] : 0;
            if ($codGarcom <= 0) {
                echo json_encode(['mesas' => [], 'totalMesas' => 0, 'totalConsumo' => 0], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $mesas = $repo->mesasFechadasDoGarcom($codGarcom, $dataIni, $dataFim);
            $totalConsumo = 0.0;
            $totalGorjeta = 0.0;
            foreach ($mesas as $m) {
                $totalConsumo += (float)($m['TOTAL_ITENS'] ?? 0);
                $totalGorjeta += (float)($m['TX_SERVICO'] ?? 0);
            }
            echo json_encode([
                'mesas'        => $mesas,
                'totalMesas'   => count($mesas),
                'totalConsumo' => $totalConsumo,
                'totalGorjeta' => $totalGorjeta,
                'dataIni'      => $dataIni,
                'dataFim'      => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  COMPARATIVO POR HORA (#2 do roadmap)
    // ════════════════════════════════════════════════════════════════════════

    public function comparativoHora(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();

        View::render('mesas/comparativo-hora', [
            'titulo'   => 'Comparativo por Hora — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function comparativoHoraApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $data   = $_GET['data'] ?? null;
            if (!$data || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $data)) {
                $data = $repo->ultimaData();
            }
            $res = $repo->comparativoPorHora($data);
            echo json_encode($res, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  FAIXAS DE HORÁRIO DO BAR (#4 do roadmap)
    // ════════════════════════════════════════════════════════════════════════

    public function faixasHorario(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        if (!isset($_GET['data_ini'])) {
            $filtros['dataIni'] = date('Y-m-d', strtotime($filtros['dataFim'] . ' -29 days'));
        }

        View::render('mesas/faixas-horario', [
            'titulo'   => 'Faixas de Horário — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function faixasHorarioApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $res = $repo->faixasHorarioBar($dataIni, $dataFim);
            echo json_encode($res, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  CORTESIA — fraude clássica do bar (forma de pagamento "CORTESIA")
    // ════════════════════════════════════════════════════════════════════════

    /** GET /mesas/cortesias — página shell */
    public function cortesias(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        if (!isset($_GET['data_ini'])) {
            $filtros['dataIni'] = date('Y-m-d', strtotime($filtros['dataFim'] . ' -29 days'));
        }

        View::render('mesas/cortesias', [
            'titulo'   => 'Análise de Cortesia — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    /** GET /api/mesas/cortesias?data_ini=&data_fim= */
    public function cortesiasApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);

            $detalhe   = $repo->cortesiasDetalhe($dataIni, $dataFim);
            $porGarcom = $repo->cortesiasPorGarcom($dataIni, $dataFim);

            // KPIs
            $qtdTotal  = count($detalhe);
            $valTotal  = 0.0;
            foreach ($detalhe as $r) $valTotal += (float)$r['VALOR'];
            $ticketMed = $qtdTotal > 0 ? $valTotal / $qtdTotal : 0;

            // Alertas: garçons acima de 2x a média
            $alertas = [];
            foreach ($porGarcom as $g) {
                if (!empty($g['ALERTA'])) {
                    $alertas[] = [
                        'garcom' => $g['GARCOM'],
                        'qtd'    => $g['QTD_CORTESIAS'],
                        'valor'  => $g['VALOR_CORTESIA'],
                        'vs_media' => $g['VS_MEDIA'],
                    ];
                }
            }

            echo json_encode([
                'detalhe'      => $detalhe,
                'porGarcom'    => $porGarcom,
                'alertas'      => $alertas,
                'kpis'         => [
                    'qtd_total'  => $qtdTotal,
                    'valor_total'=> $valTotal,
                    'ticket_medio' => $ticketMed,
                ],
                'dataIni'      => $dataIni,
                'dataFim'      => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  EXCEÇÕES NO CAIXA — anti-fraude bar (v1.4.27)
    // ════════════════════════════════════════════════════════════════════════

    /** GET /mesas/excecoes-caixa — página shell */
    public function excecoesCaixa(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        if (!isset($_GET['data_ini'])) {
            $filtros['dataIni'] = date('Y-m-d', strtotime($filtros['dataFim'] . ' -29 days'));
        }

        View::render('mesas/excecoes-caixa', [
            'titulo'   => 'Exceções no Caixa — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    /** GET /api/mesas/excecoes-caixa?data_ini=&data_fim=&t_canc=&t_desc=&h_longa= */
    public function excecoesCaixaApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $tCanc   = isset($_GET['t_canc'])  ? max(0.1, (float)$_GET['t_canc'])  : 5.0;
            $tDesc   = isset($_GET['t_desc'])  ? max(0.1, (float)$_GET['t_desc'])  : 10.0;
            $hLonga  = isset($_GET['h_longa']) ? max(1,   (int)$_GET['h_longa'])   : 4;

            $linhas = $repo->excecoesPorGarcom($dataIni, $dataFim, $tCanc, $tDesc, $hLonga);

            // KPIs agregados
            $totMesas = $totCanc = $totLongas = 0;
            $totFat = $totDesc = $totValCanc = 0.0;
            foreach ($linhas as $r) {
                $totMesas   += (int)$r['MESAS_TOTAL'];
                $totCanc    += (int)$r['MESAS_CANCELADAS'];
                $totLongas  += (int)$r['COMANDAS_LONGAS'];
                $totFat     += (float)$r['FATURAMENTO'];
                $totDesc    += (float)$r['DESCONTO_TOTAL'];
                $totValCanc += (float)$r['VALOR_CANCELADO'];
            }

            // Alertas: garçons vermelhos
            $alertas = [];
            foreach ($linhas as $r) {
                if ($r['SEMAFORO'] === 'vermelho') {
                    $alertas[] = [
                        'garcom'  => $r['GARCOM'],
                        'score'   => $r['SCORE'],
                        'motivo'  => sprintf('%.1f%% cancelamento · %.1f%% desconto · %d longas',
                            $r['PCT_CANCELADAS'], $r['PCT_DESCONTO'], $r['COMANDAS_LONGAS']),
                    ];
                }
            }

            echo json_encode([
                'linhas'      => $linhas,
                'kpis'        => [
                    'mesas_total'     => $totMesas,
                    'canceladas'      => $totCanc,
                    'valor_cancelado' => $totValCanc,
                    'desconto_total'  => $totDesc,
                    'faturamento'     => $totFat,
                    'comandas_longas' => $totLongas,
                ],
                'alertas'     => $alertas,
                'thresholds'  => ['t_canc' => $tCanc, 't_desc' => $tDesc, 'h_longa' => $hLonga],
                'dataIni'     => $dataIni,
                'dataFim'     => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/excecoes-detalhe?cod_garcom=&data_ini=&data_fim= */
    public function excecoesDetalheApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $codGarcom = isset($_GET['cod_garcom']) ? (int)$_GET['cod_garcom'] : 0;
            if ($codGarcom <= 0) {
                echo json_encode(['mesas' => []], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $mesas = $repo->excecoesDetalhe($codGarcom, $dataIni, $dataFim);
            echo json_encode([
                'mesas'   => $mesas,
                'dataIni' => $dataIni,
                'dataFim' => $dataFim,
            ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/mesas/itens-mesa?cod_abertura= */
    public function itensMesaApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $codAbertura = isset($_GET['cod_abertura']) ? (int)$_GET['cod_abertura'] : 0;
            if ($codAbertura <= 0) {
                echo json_encode(['itens' => []], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $repo  = $this->repo();
            $itens = $repo->itensDaMesa($codAbertura);
            echo json_encode(['itens' => $itens], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }
}
