<?php

namespace App\Controllers;

use App\Core\Database;
use App\Core\View;
use App\Repositories\FinanceiroRepository;
use App\Repositories\EstoqueRepository;
use App\Repositories\ClientesRepository;
use App\Services\DashboardService;

class AlertasController
{
    public function index(): void
    {
        $config = $this->carregarConfig();
        View::render('alertas/index', [
            'titulo' => 'Alertas Automaticos',
            'config' => $config,
            'ano'    => date('Y'),
        ]);
    }

    public function api(): void
    {
        header('Content-Type: application/json; charset=utf-8');

        try {
            $pdo = Database::conectar();

            $finRepo = new FinanceiroRepository($pdo);
            $estRepo = new EstoqueRepository($pdo);
            $cliRepo = new ClientesRepository($pdo);
            $svc     = new DashboardService();

            $finKpis  = [];
            $estKpis  = [];
            $cliInat  = 0;
            $metaData = [];
            $indData  = [];

            try { $finKpis  = $finRepo->kpis();            } catch (\Throwable) {}
            try { $estKpis  = $estRepo->kpisMinimos();     } catch (\Throwable) {}
            try { $cliInat  = $cliRepo->countInativos(60); } catch (\Throwable) {}
            try { $metaData = $svc->metaVsRealizado();     } catch (\Throwable) {}
            try { $indData  = $svc->indicadores();         } catch (\Throwable) {}

            $aReceber    = (float)($finKpis['A_RECEBER']        ?? 0);
            $aPagar      = (float)($finKpis['A_PAGAR']          ?? 0);
            $vencReceber = (float)($finKpis['VENCIDOS_RECEBER'] ?? 0);
            $vencPagar   = (float)($finKpis['VENCIDOS_PAGAR']   ?? 0);

            $totalAbaixo = (int)  ($estKpis['TOTAL_ABAIXO']  ?? 0);
            $deficitTotal= (float)($estKpis['DEFICIT_TOTAL'] ?? 0);

            $temMeta   = (bool) ($metaData['tem_meta']  ?? false);
            $percMeta  = (float)($metaData['perc_meta'] ?? 0);
            $diaRef    = (int)  ($metaData['dia_ref']   ?? 0);

            $deltaMes  = isset($indData['delta_mes_anterior'])
                         ? (float)$indData['delta_mes_anterior']
                         : null;

            $alertas = [];

            // Contas a pagar vencidas
            if ($vencPagar > 0) {
                $percVencPagar = $aPagar > 0 ? round($vencPagar / $aPagar * 100, 1) : 100;
                $descPagar = 'Voce tem R$ ' . number_format($vencPagar, 2, ',', '.')
                    . ' em contas que ja passaram do vencimento e ainda nao foram pagas'
                    . ' (' . number_format($percVencPagar, 1, ',', '.') . '% do total a pagar).'
                    . ' Juros e multas podem estar sendo acumulados. Priorize esses pagamentos para evitar problemas com fornecedores e protestos.';
                $sev = $percVencPagar >= 30 ? 'critico' : 'atencao';
            } else {
                $descPagar = 'Nenhuma conta a pagar esta vencida.';
                $sev = 'ok';
            }
            $alertas[] = [
                'id'         => 'fin_pagar_vencido',
                'categoria'  => 'Financeiro',
                'icone'      => 'bi-calendar-x-fill',
                'titulo'     => 'Contas a Pagar Vencidas',
                'descricao'  => $descPagar,
                'valor'      => $vencPagar,
                'link'       => '/financeiro/contas-pagar',
                'severidade' => $sev,
            ];

            // Inadimplencia
            if ($vencReceber > 0) {
                $percInadim = $aReceber > 0 ? round($vencReceber / $aReceber * 100, 1) : 100;
                $descInadim = 'Ha R$ ' . number_format($vencReceber, 2, ',', '.')
                    . ' em titulos a receber que ja venceram'
                    . ' (' . number_format($percInadim, 1, ',', '.') . '% do total a receber).'
                    . ' Clientes com valores em aberto precisam ser cobrados imediatamente.'
                    . ' Quanto mais tempo sem cobranca, menor a chance de recebimento.';
                $sevInadim = $percInadim >= 20 ? 'critico' : 'atencao';
            } else {
                $descInadim = 'Nenhum titulo a receber esta vencido. Excelente!';
                $sevInadim = 'ok';
            }
            $alertas[] = [
                'id'         => 'fin_inadimplencia',
                'categoria'  => 'Financeiro',
                'icone'      => 'bi-exclamation-circle-fill',
                'titulo'     => 'Inadimplencia - Titulos Vencidos a Receber',
                'descricao'  => $descInadim,
                'valor'      => $vencReceber,
                'link'       => '/relatorios/inadimplencia',
                'severidade' => $sevInadim,
            ];

            // Saldo liquido
            if ($aPagar > $aReceber && ($aPagar - $aReceber) > 1000) {
                $diferenca = $aPagar - $aReceber;
                $descSaldo = 'Suas obrigacoes a pagar (R$ ' . number_format($aPagar, 2, ',', '.')
                    . ') superam o que voce tem a receber (R$ ' . number_format($aReceber, 2, ',', '.')
                    . ') em R$ ' . number_format($diferenca, 2, ',', '.')
                    . '. Isso pode indicar pressao no fluxo de caixa. Avalie antecipar recebimentos ou negociar prazos com fornecedores.';
                $sevSaldo = 'atencao';
            } else {
                $descSaldo = 'Saldo positivo: A Receber (R$ ' . number_format($aReceber, 2, ',', '.')
                    . ') supera o A Pagar (R$ ' . number_format($aPagar, 2, ',', '.') . '). Fluxo de caixa saudavel.';
                $sevSaldo = 'ok';
            }
            $alertas[] = [
                'id'         => 'fin_saldo_liquido',
                'categoria'  => 'Financeiro',
                'icone'      => 'bi-arrow-left-right',
                'titulo'     => 'Saldo do Fluxo de Caixa (A Pagar vs A Receber)',
                'descricao'  => $descSaldo,
                'valor'      => $aPagar - $aReceber,
                'link'       => '/financeiro/fluxo-caixa',
                'severidade' => $sevSaldo,
            ];

            // Estoque abaixo do minimo
            if ($totalAbaixo > 20) {
                $estSev = 'critico';
            } elseif ($totalAbaixo > 0) {
                $estSev = 'atencao';
            } else {
                $estSev = 'ok';
            }
            if ($totalAbaixo > 0) {
                $descEst = $totalAbaixo . ' produto' . ($totalAbaixo === 1 ? '' : 's')
                    . ' esta' . ($totalAbaixo === 1 ? '' : 'o') . ' abaixo do estoque minimo definido,'
                    . ' com deficit total de R$ ' . number_format($deficitTotal, 2, ',', '.')
                    . '. Produtos sem estoque suficiente podem causar perda de vendas e insatisfacao de clientes.'
                    . ' Acione os fornecedores para reposicao urgente.';
            } else {
                $descEst = 'Todos os produtos estao dentro do estoque minimo. Nenhuma acao necessaria.';
            }
            $alertas[] = [
                'id'         => 'est_abaixo_minimo',
                'categoria'  => 'Estoque',
                'icone'      => 'bi-exclamation-triangle-fill',
                'titulo'     => 'Produtos Abaixo do Estoque Minimo',
                'descricao'  => $descEst,
                'valor'      => (float)$totalAbaixo,
                'link'       => '/estoque/minimos',
                'severidade' => $estSev,
            ];

            // Ritmo da meta mensal
            if ($temMeta && $diaRef > 7) {
                if ($percMeta < 60) {
                    $metaSev  = 'critico';
                    $metaDesc = 'A meta do mes esta em apenas ' . number_format($percMeta, 1, ',', '.') . '%.'
                        . ' No ritmo atual, a meta NAO sera atingida ao final do mes.'
                        . ' E necessaria uma acao comercial urgente: foque nos clientes de maior potencial,'
                        . ' ofertas especiais ou contato ativo com a carteira.';
                } elseif ($percMeta < 80) {
                    $metaSev  = 'atencao';
                    $metaDesc = 'A meta do mes esta em ' . number_format($percMeta, 1, ',', '.') . '%.'
                        . ' O ritmo atual esta abaixo do esperado para essa altura do mes.'
                        . ' Intensifique as acoes comerciais para garantir o atingimento do objetivo.';
                } else {
                    $metaSev  = 'ok';
                    $metaDesc = 'Meta em ' . number_format($percMeta, 1, ',', '.') . '%. Ritmo adequado para o periodo.';
                }
                $alertas[] = [
                    'id'         => 'vnd_meta_ritmo',
                    'categoria'  => 'Vendas',
                    'icone'      => 'bi-bullseye',
                    'titulo'     => 'Ritmo da Meta Mensal de Vendas',
                    'descricao'  => $metaDesc,
                    'valor'      => $percMeta,
                    'link'       => '/metas',
                    'severidade' => $metaSev,
                ];
            }

            // Queda de faturamento
            if ($deltaMes !== null) {
                if ($deltaMes < -20) {
                    $quedaSev = 'critico';
                } elseif ($deltaMes < -10) {
                    $quedaSev = 'atencao';
                } else {
                    $quedaSev = 'ok';
                }
                if ($deltaMes < 0) {
                    $quedaDesc = 'O faturamento deste mes caiu ' . number_format(abs($deltaMes), 1, ',', '.') . '%'
                        . ' em comparacao ao mes anterior. Uma queda acima de 10% merece investigacao:'
                        . ' verifique se houve perda de clientes, reducao de pedidos ou problemas operacionais.';
                } else {
                    $quedaDesc = 'O faturamento cresceu ' . number_format($deltaMes, 1, ',', '.') . '%'
                        . ' em relacao ao mes anterior. Bom resultado!';
                }
                $alertas[] = [
                    'id'         => 'vnd_queda_faturamento',
                    'categoria'  => 'Vendas',
                    'icone'      => 'bi-graph-down-arrow',
                    'titulo'     => 'Variacao do Faturamento vs Mes Anterior',
                    'descricao'  => $quedaDesc,
                    'valor'      => $deltaMes,
                    'link'       => '/vendas/mensais',
                    'severidade' => $quedaSev,
                ];
            }

            // Clientes inativos
            if ($cliInat > 50) {
                $cliSev = 'critico';
            } elseif ($cliInat > 15) {
                $cliSev = 'atencao';
            } else {
                $cliSev = 'ok';
            }
            if ($cliInat > 0) {
                $descCli = $cliInat . ' cliente' . ($cliInat === 1 ? '' : 's')
                    . ' nao compra' . ($cliInat === 1 ? '' : 'm') . ' ha mais de 60 dias.'
                    . ' Clientes inativos representam receita perdida e podem estar comprando na concorrencia.'
                    . ' Entre em contato para entender o motivo e oferecer condicoes especiais para reativacao.';
            } else {
                $descCli = 'Todos os clientes ativos compraram nos ultimos 60 dias. Base saudavel!';
            }
            $alertas[] = [
                'id'         => 'cli_inativos_60',
                'categoria'  => 'Clientes',
                'icone'      => 'bi-person-x-fill',
                'titulo'     => 'Clientes Inativos ha Mais de 60 Dias',
                'descricao'  => $descCli,
                'valor'      => (float)$cliInat,
                'link'       => '/clientes/inativos',
                'severidade' => $cliSev,
            ];

            $alertasFiltrados = array_values(array_filter($alertas, fn($a) => $a['severidade'] !== 'ok'));
            $totalCritico = count(array_filter($alertasFiltrados, fn($a) => $a['severidade'] === 'critico'));
            $totalAtencao = count(array_filter($alertasFiltrados, fn($a) => $a['severidade'] === 'atencao'));

            echo json_encode([
                'ok'    => true,
                'dados' => [
                    'total_critico' => $totalCritico,
                    'total_atencao' => $totalAtencao,
                    'alertas'       => $alertasFiltrados,
                    'gerado_em'     => date('d/m/Y H:i'),
                ],
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }

        exit;
    }

    public function count(): void
    {
        header('Content-Type: application/json; charset=utf-8');

        try {
            $pdo = Database::conectar();
            $vencPagar   = 0.0;
            $vencReceber = 0.0;
            $totalAbaixo = 0;

            try {
                $finRepo     = new FinanceiroRepository($pdo);
                $finKpis     = $finRepo->kpis();
                $vencPagar   = (float)($finKpis['VENCIDOS_PAGAR']  ?? 0);
                $vencReceber = (float)($finKpis['VENCIDOS_RECEBER'] ?? 0);
            } catch (\Throwable) {}

            try {
                $estRepo     = new EstoqueRepository($pdo);
                $estKpis     = $estRepo->kpisMinimos();
                $totalAbaixo = (int)($estKpis['TOTAL_ABAIXO'] ?? 0);
            } catch (\Throwable) {}

            $critico = ($vencPagar > 0 ? 1 : 0) + ($vencReceber > 0 ? 1 : 0);
            $atencao = ($totalAbaixo > 0 ? 1 : 0);
            echo json_encode(['critico' => $critico, 'atencao' => $atencao], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);

        } catch (\Throwable) {
            echo json_encode(['critico' => 0, 'atencao' => 0]);
        }

        exit;
    }

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