<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\ArquivoFiscal;
use Exception;
use ZipArchive;

class ArquivosFiscaisController extends BaseController
{
    private ArquivoFiscal $model;

    public function __construct($request, $response)
    {
        parent::__construct($request, $response);
        $this->model = new ArquivoFiscal($this->db);
    }

    /**
     * Lista arquivos fiscais
     */
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('arquivos-fiscais')) {
            $this->response->forbidden('Você não tem permissão para visualizar arquivos fiscais.');
            return;
        }

        try {
            $filtros = [
                'empresa_id' => $this->request->get('empresa_id'),
                'tipo_documento' => $this->request->get('tipo_documento'),
                'status' => $this->request->get('status'),
                'tipo_operacao' => $this->request->get('tipo_operacao'),
                'mes' => $this->request->get('mes'),
                'ano' => $this->request->get('ano'),
                'chave_acesso' => $this->request->get('chave_acesso'),
            ];

            $arquivos = $this->model->listar($filtros);

            // Busca empresas para filtro
            $stmt = $this->db->query("SELECT id, razao_social FROM empresas ORDER BY razao_social");
            $empresas = $stmt->fetchAll();

            $this->view('arquivos-fiscais/index', [
                'arquivos' => $arquivos,
                'empresas' => $empresas,
                'filtros' => $filtros,
                'pageTitle' => 'Arquivos Fiscais'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao listar arquivos fiscais: " . $e->getMessage());
            $this->error('Erro ao carregar arquivos fiscais');
        }
    }

    /**
     * Download de XML
     */
    public function downloadXml(): void
    {
        try {
            $id = $this->request->get('id');
            $arquivo = $this->model->buscarPorId((int)$id);

            if (!$arquivo) {
                $this->error('Arquivo não encontrado');
                return;
            }

            $xmlPath = ROOT_PATH . $arquivo['xml_path'];

            if (!file_exists($xmlPath)) {
                $this->error('Arquivo XML não encontrado no servidor');
                return;
            }

            header('Content-Type: application/xml');
            header('Content-Disposition: attachment; filename="' . basename($xmlPath) . '"');
            header('Content-Length: ' . filesize($xmlPath));
            readfile($xmlPath);
            exit;

        } catch (Exception $e) {
            error_log("Erro ao baixar XML: " . $e->getMessage());
            $this->error('Erro ao baixar arquivo');
        }
    }

    /**
     * Download de PDF
     */
    public function downloadPdf(): void
    {
        try {
            $id = $this->request->get('id');
            $arquivo = $this->model->buscarPorId((int)$id);

            if (!$arquivo || empty($arquivo['pdf_path'])) {
                $this->error('PDF não encontrado');
                return;
            }

            $pdfPath = ROOT_PATH . $arquivo['pdf_path'];

            if (!file_exists($pdfPath)) {
                $this->error('Arquivo PDF não encontrado no servidor');
                return;
            }

            header('Content-Type: application/pdf');
            header('Content-Disposition: attachment; filename="' . basename($pdfPath) . '"');
            header('Content-Length: ' . filesize($pdfPath));
            readfile($pdfPath);
            exit;

        } catch (Exception $e) {
            error_log("Erro ao baixar PDF: " . $e->getMessage());
            $this->error('Erro ao baixar arquivo');
        }
    }

    /**
     * Exporta XMLs ou PDFs para contador (ZIP)
     */
    public function exportarContador(): void
    {
        try {
            $empresaId = $this->request->post('empresa_id');
            $mes = $this->request->post('mes');
            $ano = $this->request->post('ano');
            $formato = $this->request->post('formato', 'xml'); // xml ou pdf
            $tipoDocumento = $this->request->post('tipo_documento'); // Opcional

            if (!$empresaId || !$mes || !$ano) {
                $this->error('Parâmetros inválidos');
                return;
            }

            $filtros = [
                'empresa_id' => $empresaId,
                'mes' => $mes,
                'ano' => $ano,
            ];

            if ($tipoDocumento) {
                $filtros['tipo_documento'] = $tipoDocumento;
            }

            $arquivos = $this->model->listar($filtros);

            if (empty($arquivos)) {
                $this->error('Nenhum arquivo encontrado para o período selecionado');
                return;
            }

            // Buscar dados da empresa para pegar CNPJ
            $stmt = $this->db->prepare("SELECT cnpj, razao_social FROM empresas WHERE id = :id");
            $stmt->execute(['id' => $empresaId]);
            $empresa = $stmt->fetch();

            if (!$empresa) {
                $this->error('Empresa não encontrada');
                return;
            }

            $cnpj = preg_replace('/\D/', '', $empresa['cnpj']);
            $anoMes = $ano . '_' . $mes;

            // Criar ZIP
            $formatoTexto = $formato === 'pdf' ? 'PDFs' : 'XMLs';
            $zipFilename = $formatoTexto . '_' . $empresa['razao_social'] . '_' . $mes . '_' . $ano . '.zip';
            $zipPath = ROOT_PATH . '/storage/temp/' . $zipFilename;

            // Cria diretório temp se não existir
            if (!is_dir(ROOT_PATH . '/storage/temp')) {
                mkdir(ROOT_PATH . '/storage/temp', 0755, true);
            }

            $zip = new \ZipArchive();
            if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
                $this->error('Erro ao criar arquivo ZIP');
                return;
            }

            $adicionados = 0;
            foreach ($arquivos as $arquivo) {
                if (empty($arquivo['chave_acesso'])) {
                    continue; // Pula vendas sem NF-e
                }

                $chaveNfe = $arquivo['chave_acesso'];

                if ($formato === 'pdf') {
                    // Buscar PDF
                    $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/pdf/' . $anoMes . '/emitidos/';
                    $possiveisNomes = [
                        'NFe_' . $chaveNfe . '.pdf',
                        'NFe_ ' . $chaveNfe . '.pdf',
                    ];

                    $pdfPath = null;
                    foreach ($possiveisNomes as $nomeArquivo) {
                        $caminhoTeste = $diretorioBase . $nomeArquivo;
                        if (file_exists($caminhoTeste)) {
                            $pdfPath = $caminhoTeste;
                            break;
                        }
                    }

                    // Tentar sem ano/mês
                    if (!$pdfPath) {
                        $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/pdf/emitidos/';
                        foreach ($possiveisNomes as $nomeArquivo) {
                            $caminhoTeste = $diretorioBase . $nomeArquivo;
                            if (file_exists($caminhoTeste)) {
                                $pdfPath = $caminhoTeste;
                                break;
                            }
                        }
                    }

                    if ($pdfPath && file_exists($pdfPath)) {
                        $zip->addFile($pdfPath, 'NFe_' . $arquivo['numero_documento'] . '.pdf');
                        $adicionados++;
                    }
                } else {
                    // Buscar XML
                    $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/xml/' . $anoMes . '/emitidos/';
                    $xmlPath = $diretorioBase . $chaveNfe . '-procNFe.xml';

                    // Tentar sem ano/mês
                    if (!file_exists($xmlPath)) {
                        $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/xml/emitidos/';
                        $xmlPath = $diretorioBase . $chaveNfe . '-procNFe.xml';
                    }

                    if (file_exists($xmlPath)) {
                        $zip->addFile($xmlPath, $chaveNfe . '-procNFe.xml');
                        $adicionados++;
                    }
                }
            }

            $zip->close();

            if ($adicionados === 0) {
                @unlink($zipPath);
                $this->error('Nenhum arquivo ' . strtoupper($formato) . ' válido encontrado');
                return;
            }

            // Download do ZIP
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . $zipFilename . '"');
            header('Content-Length: ' . filesize($zipPath));
            readfile($zipPath);

            // Remove ZIP temporário
            @unlink($zipPath);
            exit;

        } catch (Exception $e) {
            error_log("Erro ao exportar para contador: " . $e->getMessage());
            $this->error('Erro ao gerar exportação: ' . $e->getMessage());
        }
    }

    /**
     * Envia XMLs por e-mail para o contador
     */
    public function enviarEmailContador(): void
    {
        try {
            $empresaId = $this->request->post('empresa_id');
            $mes = $this->request->post('mes');
            $ano = $this->request->post('ano');
            $tipoDocumento = $this->request->post('tipo_documento');

            if (!$empresaId || !$mes || !$ano) {
                $this->error('Parâmetros inválidos');
                return;
            }

            // Buscar dados da empresa e e-mail do contador
            $stmt = $this->db->prepare("SELECT cnpj, razao_social, contador_email FROM empresas WHERE id = :id");
            $stmt->execute(['id' => $empresaId]);
            $empresa = $stmt->fetch();

            if (!$empresa) {
                $this->error('Empresa não encontrada');
                return;
            }

            $emailContador = $empresa['contador_email'];

            if (empty($emailContador)) {
                $this->error('E-mail do contador não cadastrado na empresa. Acesse o cadastro de empresas e preencha o e-mail do contador.');
                return;
            }

            // Validar e-mail
            if (!filter_var($emailContador, FILTER_VALIDATE_EMAIL)) {
                $this->error('E-mail do contador inválido. Verifique o cadastro da empresa.');
                return;
            }

            $filtros = [
                'empresa_id' => $empresaId,
                'mes' => $mes,
                'ano' => $ano,
            ];

            if ($tipoDocumento) {
                $filtros['tipo_documento'] = $tipoDocumento;
            }

            $arquivos = $this->model->listar($filtros);

            if (empty($arquivos)) {
                $this->error('Nenhum arquivo encontrado para o período selecionado');
                return;
            }

            $formato = $this->request->post('formato', 'xml'); // xml ou pdf

            $cnpj = preg_replace('/\D/', '', $empresa['cnpj']);
            $anoMes = $ano . '_' . $mes;

            // Criar ZIP temporário
            $formatoTexto = $formato === 'pdf' ? 'PDFs' : 'XMLs';
            $zipFilename = $formatoTexto . '_' . $empresa['razao_social'] . '_' . $mes . '_' . $ano . '.zip';
            $zipPath = ROOT_PATH . '/storage/temp/' . $zipFilename;

            if (!is_dir(ROOT_PATH . '/storage/temp')) {
                mkdir(ROOT_PATH . '/storage/temp', 0755, true);
            }

            $zip = new \ZipArchive();
            if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
                $this->error('Erro ao criar arquivo ZIP');
                return;
            }

            $adicionados = 0;

            if ($formato === 'pdf') {
                // Buscar PDFs individualmente
                foreach ($arquivos as $arquivo) {
                    if (empty($arquivo['chave_acesso'])) continue;

                    $chaveNfe = $arquivo['chave_acesso'];
                    $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/pdf/' . $anoMes . '/emitidos/';
                    $possiveisNomes = ['NFe_' . $chaveNfe . '.pdf', 'NFe_ ' . $chaveNfe . '.pdf'];

                    $pdfPath = null;
                    foreach ($possiveisNomes as $nomeArquivo) {
                        if (file_exists($diretorioBase . $nomeArquivo)) {
                            $pdfPath = $diretorioBase . $nomeArquivo;
                            break;
                        }
                    }

                    if (!$pdfPath) {
                        $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/pdf/emitidos/';
                        foreach ($possiveisNomes as $nomeArquivo) {
                            if (file_exists($diretorioBase . $nomeArquivo)) {
                                $pdfPath = $diretorioBase . $nomeArquivo;
                                break;
                            }
                        }
                    }

                    if ($pdfPath) {
                        $zip->addFile($pdfPath, 'NFe_' . $arquivo['numero_documento'] . '.pdf');
                        $adicionados++;
                    }
                }
            } else {
                // Pegar TODOS os XMLs da pasta do período
                $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/xml/' . $anoMes . '/assinados/';

                if (is_dir($diretorioBase)) {
                    $arquivosXml = glob($diretorioBase . '*.xml');
                    foreach ($arquivosXml as $xmlPath) {
                        $zip->addFile($xmlPath, basename($xmlPath));
                        $adicionados++;
                    }
                }

                // Tentar sem ano/mês
                if ($adicionados === 0) {
                    $diretorioBase = ROOT_PATH . '/src/Integrations/NFe/arquivos/' . $cnpj . '/nfe/xml/assinados/';
                    if (is_dir($diretorioBase)) {
                        $arquivosXml = glob($diretorioBase . '*.xml');
                        foreach ($arquivosXml as $xmlPath) {
                            $zip->addFile($xmlPath, basename($xmlPath));
                            $adicionados++;
                        }
                    }
                }
            }

            $zip->close();

            if ($adicionados === 0) {
                @unlink($zipPath);
                $this->error('Nenhum arquivo ' . strtoupper($formato) . ' encontrado');
                return;
            }

            // Enviar e-mail
            $mesNome = [
                '01' => 'Janeiro', '02' => 'Fevereiro', '03' => 'Março', '04' => 'Abril',
                '05' => 'Maio', '06' => 'Junho', '07' => 'Julho', '08' => 'Agosto',
                '09' => 'Setembro', '10' => 'Outubro', '11' => 'Novembro', '12' => 'Dezembro'
            ][$mes] ?? $mes;

            $arquivoTexto = $formato === 'pdf' ? 'PDFs (DANFEs)' : 'XMLs';
            $assunto = "{$formatoTexto} de NF-e - {$empresa['razao_social']} - {$mesNome}/{$ano}";
            $mensagem = "
                <h3>Arquivos Fiscais - {$empresa['razao_social']}</h3>
                <p><strong>Período:</strong> {$mesNome}/{$ano}</p>
                <p><strong>Total de {$arquivoTexto}:</strong> {$adicionados}</p>
                <p>Em anexo, seguem os arquivos {$arquivoTexto} das Notas Fiscais Eletrônicas do período solicitado.</p>
                <hr>
                <p><small>E-mail gerado automaticamente pelo sistema.</small></p>
            ";

            // Enviar e-mail usando PHPMailer
            $resultado = \App\Helpers\MailHelper::sendWithAttachment(
                $emailContador,
                $assunto,
                $mensagem,
                $zipPath,
                $zipFilename
            );

            // Remove ZIP temporário
            @unlink($zipPath);

            if ($resultado['success']) {
                $this->success("Enviamos os arquivos para o e-mail: {$emailContador}", [
                    'email' => $emailContador,
                    'total_arquivos' => $adicionados,
                    'formato' => $formatoTexto
                ]);
            } else {
                $this->error($resultado['message']);
            }

        } catch (\Exception $e) {
            $this->error('Erro: ' . $e->getMessage());
        }
    }

    /**
     * Gera SPED Fiscal
     */
    public function gerarSpedFiscal(): void
    {
        try {
            $empresaId = $this->request->post('empresa_id');
            $mes = $this->request->post('mes');
            $ano = $this->request->post('ano');

            if (!$empresaId || !$mes || !$ano) {
                $this->error('Parâmetros inválidos');
                return;
            }

            $arquivos = $this->model->listar([
                'empresa_id' => $empresaId,
                'mes' => $mes,
                'ano' => $ano,
                'tipo_documento' => 'NFe' // SPED Fiscal só NF-e
            ]);

            // TODO: Implementar geração real do SPED usando biblioteca
            // Por enquanto, retorna informações básicas

            $this->success('SPED Fiscal gerado com sucesso', [
                'total_registros' => count($arquivos),
                'periodo' => "$mes/$ano",
                'mensagem' => 'Implementação completa em desenvolvimento'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao gerar SPED Fiscal: " . $e->getMessage());
            $this->error('Erro ao gerar SPED Fiscal');
        }
    }

    /**
     * Gera SPED Contribuições
     */
    public function gerarSpedContribuicoes(): void
    {
        try {
            $empresaId = $this->request->post('empresa_id');
            $mes = $this->request->post('mes');
            $ano = $this->request->post('ano');

            if (!$empresaId || !$mes || !$ano) {
                $this->error('Parâmetros inválidos');
                return;
            }

            $arquivos = $this->model->listar([
                'empresa_id' => $empresaId,
                'mes' => $mes,
                'ano' => $ano
            ]);

            // TODO: Implementar geração real do SPED Contribuições

            $this->success('SPED Contribuições gerado com sucesso', [
                'total_registros' => count($arquivos),
                'periodo' => "$mes/$ano",
                'mensagem' => 'Implementação completa em desenvolvimento'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao gerar SPED Contribuições: " . $e->getMessage());
            $this->error('Erro ao gerar SPED Contribuições');
        }
    }

    /**
     * Deleta arquivo fiscal
     */
    public function deletar(): void
    {
        try {
            $id = $this->request->post('id');
            $arquivo = $this->model->buscarPorId((int)$id);

            if (!$arquivo) {
                $this->error('Arquivo não encontrado');
                return;
            }

            // Remove arquivos físicos
            if (!empty($arquivo['xml_path']) && file_exists(ROOT_PATH . $arquivo['xml_path'])) {
                @unlink(ROOT_PATH . $arquivo['xml_path']);
            }

            if (!empty($arquivo['pdf_path']) && file_exists(ROOT_PATH . $arquivo['pdf_path'])) {
                @unlink(ROOT_PATH . $arquivo['pdf_path']);
            }

            // Remove do banco
            $this->model->deletar((int)$id);

            $this->success('Arquivo removido com sucesso');

        } catch (Exception $e) {
            error_log("Erro ao deletar arquivo: " . $e->getMessage());
            $this->error('Erro ao remover arquivo');
        }
    }
}

