<?php

namespace App\Controllers;

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

class FinanceiroController
{
    private function repo(): FinanceiroRepository
    {
        return new FinanceiroRepository(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-01');
            $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   = isset($_GET['ano']) && ctype_digit($_GET['ano']) ? (int)$_GET['ano'] : (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-01', strtotime($ultimaFallback));
        $dataFim = $_GET['data_fim'] ?? $ultimaFallback;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = date('Y-m-01', strtotime($ultimaFallback));
        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 fluxoCaixa(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();

        View::render('financeiro/fluxo-caixa', [
            'titulo'   => 'Fluxo de Caixa — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

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

        View::render('financeiro/contas-receber', [
            'titulo'   => 'Contas a Receber — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

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

        View::render('financeiro/contas-pagar', [
            'titulo'   => 'Contas a Pagar — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

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

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

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

        View::render('financeiro/caixa', [
            'titulo'   => 'Caixa — 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/financeiro/kpis */
    public function kpisApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo  = $this->repo();
            $kpis  = $repo->kpis();
            $anos  = $repo->anosDisponiveis();
            $ultima = $repo->ultimaData();
            echo json_encode([
                'kpis'       => $kpis,
                'anos'       => $anos,
                'ultimaData' => $ultima,
            ], 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/financeiro/fluxo-caixa?data_ini=&data_fim=&ano= */
    public function fluxoCaixaApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $anoSel = isset($_GET['ano']) && ctype_digit($_GET['ano']) ? (int)$_GET['ano'] : (int)substr($dataIni, 0, 4);
            $mensal = $repo->fluxoCaixaMensal($anoSel);
            $diario = $repo->fluxoCaixaDiario($dataIni, $dataFim);
            echo json_encode([
                'mensal'  => $mensal,
                'diario'  => $diario,
                'anoSel'  => $anoSel,
                '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/financeiro/contas-receber?data_ini=&data_fim=&situacao= */
    public function contasReceberApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo     = $this->repo();
            $ultima   = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            // Expand to 6 months ahead if no explicit data_fim
            if (!isset($_GET['data_fim'])) {
                $dataFim = date('Y-m-d', strtotime($ultima . ' +180 days'));
            }
            $situacao = in_array($_GET['situacao'] ?? '', ['aberto', 'todos']) ? ($_GET['situacao'] ?? 'aberto') : 'aberto';
            $linhas   = $repo->contasReceber($dataIni, $dataFim, $situacao);
            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/financeiro/contas-pagar?data_ini=&data_fim=&situacao= */
    public function contasPagarApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo     = $this->repo();
            $ultima   = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            if (!isset($_GET['data_fim'])) {
                $dataFim = date('Y-m-d', strtotime($ultima . ' +180 days'));
            }
            $situacao = in_array($_GET['situacao'] ?? '', ['aberto', 'todos']) ? ($_GET['situacao'] ?? 'aberto') : 'aberto';
            $linhas   = $repo->contasPagar($dataIni, $dataFim, $situacao);
            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/financeiro/dre?ano= */
    public function dreApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $anoSel = isset($_GET['ano']) && ctype_digit($_GET['ano']) ? (int)$_GET['ano'] : (int)date('Y');
            $linhas = $repo->dreMensal($anoSel);
            $anos   = $repo->anosDisponiveis();

            // Heuristica: CMV nao confiavel quando soma de CMV >= soma da Receita Liquida
            // ou >50% dos meses com CMV >= Receita. Acontece em bar/distribuidora onde
            // o ERP soma compras maiores que as vendas do mes (estocagem antecipada),
            // ou nao grava custo cadastrado nos itens. Espelha a logica de VendasRepository::cmvConfiavel().
            $totCmv = 0.0; $totFat = 0.0; $mRuins = 0; $mValidos = 0;
            foreach ($linhas as $r) {
                $cmv = (float)($r['CMV'] ?? 0);
                $fat = (float)($r['RECEITA_BRUTA'] ?? 0) - (float)($r['DESCONTOS'] ?? 0);
                $totCmv += $cmv; $totFat += $fat;
                if ($fat > 0) { $mValidos++; if ($cmv >= $fat) $mRuins++; }
            }
            $confiavel = true;
            if ($totFat > 0 || $totCmv > 0) {
                if ($totCmv >= $totFat) $confiavel = false;
                elseif ($mValidos > 0 && ($mRuins / $mValidos) > 0.5) $confiavel = false;
            }

            echo json_encode([
                'linhas'    => $linhas,
                'anoSel'    => $anoSel,
                'anos'      => $anos,
                'confiavel' => $confiavel,
            ], 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/financeiro/caixa?data_ini=&data_fim= */
    public function caixaApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo   = $this->repo();
            $ultima = $repo->ultimaData();
            [$dataIni, $dataFim] = $this->parseDatas($ultima);
            $linhas = $repo->caixaMovimentos($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;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  DETALHE DE 1 CAIXA — formas + total do turno
    // ════════════════════════════════════════════════════════════════════════

    public function caixaDetalheApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $dataAb   = $_GET['data_ab'] ?? '';
            $horaAb   = $_GET['hora_ab'] ?? '';
            $dataFech = $_GET['data_fech'] ?? null;
            $horaFech = $_GET['hora_fech'] ?? null;
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataAb)) {
                echo json_encode(['erro' => 'data_ab inválida'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $config = $this->config();
            $codEmpresa = isset($config['cod_empresa']) ? (int)$config['cod_empresa'] : null;
            $repo = $this->repo();
            $res = $repo->caixaDetalhe($dataAb, $horaAb, $dataFech, $horaFech, $codEmpresa);
            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;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  MIX DE PAGAMENTO COMPLETO — sem filtro de operação (fiel ao ERP)
    // ════════════════════════════════════════════════════════════════════════

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

        View::render('financeiro/mix-pagamento', [
            'titulo'   => 'Mix de Pagamento — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function mixPagamentoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo = $this->repo();
            $config = $this->config();
            $codEmpresa = isset($config['cod_empresa']) ? (int)$config['cod_empresa'] : null;
            [$dataIni, $dataFim] = $this->parseDatas($repo->ultimaData());
            $res = $repo->mixPagamentoCompleto($dataIni, $dataFim, $codEmpresa);
            $total = 0.0;
            foreach ($res['detalhe'] as $r) $total += (float)$r['VALOR'];
            echo json_encode([
                'grupos'  => $res['grupos'],
                'detalhe' => $res['detalhe'],
                'total'   => $total,
                'qtd_formas' => count($res['detalhe']),
                '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;
    }
}
