<?php

namespace App\Controllers;

use App\Core\Database;
use App\Core\View;
use App\Repositories\VendasRepository;
use App\Repositories\ComprasRepository;
use App\Repositories\ClientesRepository;
use App\Repositories\ProdutosRepository;
use App\Repositories\EstoqueRepository;
use App\Repositories\PessoalRepository;
use App\Repositories\MesasRepository;
use App\Repositories\FinanceiroRepository;

class RelatoriosController
{
    private function pdo(): \PDO { return Database::conectar(); }

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

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

    private function safe(callable $fn, mixed $default = []): mixed
    {
        try {
            return $fn();
        } catch (\Throwable $e) {
            error_log('[Relatorios] ' . $e->getMessage());
            return $default;
        }
    }

    private function filtrosDatas(mixed $repo, string $ini = '', string $fim = ''): array
    {
        $ultima = method_exists($repo, 'ultimaData') ? $repo->ultimaData() : date('Y-m-d');

        // Padrão: session (ano+mês) → mês completo; sem session → últimos 30 dias
        $sessAno = isset($_SESSION['filtro_ano']) ? (int)$_SESSION['filtro_ano'] : null;
        $sessMes = isset($_SESSION['filtro_mes']) ? (int)$_SESSION['filtro_mes'] : null;

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

        $dataIni = $_GET['data_ini'] ?? ($ini ?: $defaultIni);
        $dataFim = $_GET['data_fim'] ?? ($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;
        return compact('dataIni', 'dataFim');
    }

    private function filtrosAno(mixed $repo): array
    {
        $anos   = method_exists($repo, 'anosDisponiveis') ? $repo->anosDisponiveis() : [date('Y')];
        $anoSel = isset($_GET['ano']) && ctype_digit($_GET['ano']) ? (int)$_GET['ano'] : (int)$anos[0];
        return compact('anos', 'anoSel');
    }

    private function exportCsv(array $rows, string $nome, array $cabecalho = []): void
    {
        header('Content-Type: text/csv; charset=UTF-8');
        header('Content-Disposition: attachment; filename="' . $nome . '_' . date('Ymd_His') . '.csv"');
        echo "\xEF\xBB\xBF"; // BOM UTF-8
        $out = fopen('php://output', 'w');
        if ($cabecalho) fputcsv($out, $cabecalho, ';');
        elseif ($rows)  fputcsv($out, array_keys($rows[0]), ';');
        foreach ($rows as $r) fputcsv($out, array_values($r), ';');
        fclose($out);
        exit;
    }

    private function renderBase(string $view, array $dados): void
    {
        $config  = $this->config();
        $status  = Database::verificar();
        View::render($view, array_merge($dados, [
            'config'   => $config,
            'conexao'  => $status,
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'empresa'  => $config['empresa']  ?? '',
            'ano'      => date('Y'),
        ]));
    }

    // ── Hub ───────────────────────────────────────────────────────────────────
    public function index(): void
    {
        $this->guardaConexao();
        $this->renderBase('relatorios/index', ['titulo' => 'Relatórios — Premium Express Gestão']);
    }

    // ── Vendas ────────────────────────────────────────────────────────────────
    public function vendas(): void
    {
        $this->guardaConexao();
        $repo    = new VendasRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->notasSaida($filtros['dataIni'], $filtros['dataFim'], null, 2000));
        $kpis    = $this->safe(fn() => $repo->kpisGestao($filtros['dataIni'], $filtros['dataFim']));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_vendas',
                ['Nota','Série','Data','Cliente','Vendedor','Total','Situação']);
        }
        $this->renderBase('relatorios/vendas', [
            'titulo' => 'Rel. Vendas — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'kpis' => $kpis,
        ]);
    }

    // ── Compras ───────────────────────────────────────────────────────────────
    public function compras(): void
    {
        $this->guardaConexao();
        $repo    = new ComprasRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->notasEntrada($filtros['dataIni'], $filtros['dataFim'], 2000));
        $kpis    = $this->safe(fn() => $repo->kpis($filtros['dataIni'], $filtros['dataFim']));
        $forn    = $this->safe(fn() => $repo->porFornecedor($filtros['dataIni'], $filtros['dataFim']));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_compras');
        }
        $this->renderBase('relatorios/compras', [
            'titulo' => 'Rel. Compras — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'kpis' => $kpis, 'forn' => $forn,
        ]);
    }

    // ── DRE ───────────────────────────────────────────────────────────────────
    public function dre(): void
    {
        $this->guardaConexao();
        $repo    = new FinanceiroRepository($this->pdo());
        $fa      = $this->filtrosAno($repo);
        $linhas  = $this->safe(fn() => $repo->dreMensal($fa['anoSel']));

        $despPath = dirname(__DIR__, 2) . '/config/despesas.json';
        $despData = file_exists($despPath) ? (json_decode(file_get_contents($despPath), true) ?? []) : [];
        $despCats = $despData['categorias'] ?? [];
        $despMes  = [];
        for ($m = 1; $m <= 12; $m++) {
            $tot = 0;
            foreach ($despCats as $cat) $tot += (float)($despData[$fa['anoSel']][$m][$cat] ?? 0);
            $despMes[$m] = $tot;
        }

        if (($_GET['formato'] ?? '') === 'csv') {
            $rows = [];
            foreach ($linhas as $r) {
                $rl  = (float)$r['RECEITA_BRUTA'] - (float)$r['DESCONTOS'];
                $mb  = $rl - (float)$r['CMV'];
                $dp  = $despMes[(int)$r['MES']] ?? 0;
                $rows[] = [$r['MES'], number_format((float)$r['RECEITA_BRUTA'],2,',','.'),
                           number_format((float)$r['CMV'],2,',','.'), number_format($mb,2,',','.'),
                           number_format($dp,2,',','.'), number_format($mb-$dp,2,',','.')];
            }
            $this->exportCsv($rows, 'relatorio_dre', ['Mês','Rec.Bruta','CMV','Margem Bruta','Despesas','Resultado']);
        }
        $this->renderBase('relatorios/dre', [
            'titulo' => 'DRE — Premium Express Gestão',
            'filtros' => $fa, 'linhas' => $linhas, 'despMes' => $despMes,
        ]);
    }

    // ── Curva ABC ─────────────────────────────────────────────────────────────
    public function curvaAbc(): void
    {
        $this->guardaConexao();
        $repo    = new ProdutosRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->curvaAbc($filtros['dataIni'], $filtros['dataFim'], 500));
        $kpis    = $this->safe(fn() => $repo->kpis($filtros['dataIni'], $filtros['dataFim']));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_curva_abc',
                ['#','Produto','Un','Classe','Qtd','Faturamento','% Fat','% Acum','Notas']);
        }
        $this->renderBase('relatorios/curva-abc', [
            'titulo' => 'Curva ABC — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'kpis' => $kpis,
        ]);
    }

    // ── Clientes ──────────────────────────────────────────────────────────────
    public function clientes(): void
    {
        $this->guardaConexao();
        $repo    = new ClientesRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->ticketMedio($filtros['dataIni'], $filtros['dataFim'], 500));
        $freq    = $this->safe(fn() => $repo->frequencia($filtros['dataIni'], $filtros['dataFim'], 500));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_clientes',
                ['Cliente','Compras','Valor Total','Ticket Médio','Última Compra']);
        }
        $this->renderBase('relatorios/clientes', [
            'titulo' => 'Rel. Clientes — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'freq' => $freq,
        ]);
    }

    // ── Garçons / Mesas ───────────────────────────────────────────────────────
    public function garcons(): void
    {
        $this->guardaConexao();
        $repo    = new MesasRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->porGarcom($filtros['dataIni'], $filtros['dataFim']));
        $kpis    = $this->safe(fn() => $repo->kpis($filtros['dataIni'], $filtros['dataFim']));
        $tempo   = $this->safe(fn() => $repo->tempoMedio($filtros['dataIni'], $filtros['dataFim']));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_garcons',
                ['Garçom','Mesas','Faturamento','Ticket Médio','Pessoas','Tx.Serviço']);
        }
        $this->renderBase('relatorios/garcons', [
            'titulo' => 'Rel. Garçons — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'kpis' => $kpis, 'tempo' => $tempo,
        ]);
    }

    // ── Estoque ───────────────────────────────────────────────────────────────
    public function estoque(): void
    {
        $this->guardaConexao();
        $repo   = new EstoqueRepository($this->pdo());
        $busca  = trim($_GET['busca'] ?? '');
        $linhas = $this->safe(fn() => $repo->posicao($busca, 1000));
        $kpis   = $this->safe(fn() => $repo->kpis());
        $min    = $this->safe(fn() => $repo->minimos(500));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_estoque',
                ['Código','Produto','Un','Estoque','Custo Unit','Vl.Custo','Vl.Venda']);
        }
        $this->renderBase('relatorios/estoque', [
            'titulo' => 'Rel. Estoque — Premium Express Gestão',
            'linhas' => $linhas, 'kpis' => $kpis, 'min' => $min, 'busca' => $busca,
        ]);
    }

    // ── Inadimplência ─────────────────────────────────────────────────────────
    public function inadimplencia(): void
    {
        $this->guardaConexao();
        $repo    = new ClientesRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $linhas  = $this->safe(fn() => $repo->inadimplentesDetalhado(1000));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_inadimplencia',
                ['Cliente','Nota','Parcela','Valor','Saldo','Vencimento','Dias Atraso']);
        }
        $this->renderBase('relatorios/inadimplencia', [
            'titulo'  => 'Inadimplência — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas,
        ]);
    }

    // ── Margem por Produto ────────────────────────────────────────────────────
    public function margem(): void
    {
        $this->guardaConexao();
        $repo   = new EstoqueRepository($this->pdo());
        $busca  = trim($_GET['busca'] ?? '');
        $linhas = $this->safe(fn() => $repo->margem(500));

        if ($busca) {
            $linhas = array_filter($linhas, fn($r) => stripos($r['DESCRICAO'], $busca) !== false);
            $linhas = array_values($linhas);
        }

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_margem',
                ['Produto','Un','Qtd','Custo','Preço Venda','Margem R$','Margem %','Val.Estoque Venda']);
        }
        $this->renderBase('relatorios/margem', [
            'titulo' => 'Margem por Produto — Premium Express Gestão',
            'linhas' => $linhas, 'busca' => $busca,
        ]);
    }

    // ── Comissões ─────────────────────────────────────────────────────────────
    public function comissoes(): void
    {
        $this->guardaConexao();
        $repo    = new MesasRepository($this->pdo());
        $filtros = $this->filtrosDatas($repo);
        $perc    = isset($_GET['perc']) && is_numeric($_GET['perc']) ? (float)$_GET['perc'] : 10.0;
        $filtros['perc'] = $perc;

        $linhas = $this->safe(fn() => $repo->comissoesPorGarcom($filtros['dataIni'], $filtros['dataFim'], $perc));
        $mensal = $this->safe(fn() => $repo->comissoesMensal($filtros['dataIni'], $filtros['dataFim'], $perc));

        if (($_GET['formato'] ?? '') === 'csv') {
            $this->exportCsv($linhas, 'relatorio_comissoes',
                ['Garçom','Mesas','Faturamento','Tx.Serviço','Comissão']);
        }
        $this->renderBase('relatorios/comissoes', [
            'titulo'  => 'Rel. Comissões — Premium Express Gestão',
            'filtros' => $filtros, 'linhas' => $linhas, 'mensal' => $mensal,
        ]);
    }
}
