<?php

namespace App\Services;

use NFePHP\NFe\Tools;
use NFePHP\NFe\Common\Standardize;
use NFePHP\Common\Certificate;
use NFePHP\DA\NFe\Danfce;

class NFCeService
{
    /**
     * Log personalizado no projeto
     */
    private function log($message)
    {
        $logFile = __DIR__ . "/../../logs/nfce_debug.log";
        $logDir = dirname($logFile);

        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }

        $timestamp = date('Y-m-d H:i:s');
        $logMessage = "[$timestamp] $message" . PHP_EOL;
        file_put_contents($logFile, $logMessage, FILE_APPEND | LOCK_EX);

        // Também log no PHP para compatibilidade
        error_log($message);
    }

    /**
     * Criar estrutura de diretórios para NFC-e
     */
    private function criarEstruturaDiretorios($cnpj)
    {
        $basePath = __DIR__ . "/../../arquivos/{$cnpj}/nfce";
        $anoMes = date('Y_m');

        $diretorios = [
            "{$basePath}/xml/{$anoMes}/assinados",
            "{$basePath}/pdf/{$anoMes}/emitidos",
            "{$basePath}/eventos"
        ];

        foreach ($diretorios as $dir) {
            if (!is_dir($dir)) {
                mkdir($dir, 0755, true);
            }
        }
    }

    /**
     * Emite NFC-e (Nota Fiscal de Consumidor Eletrônica)
     */
    public function emitir($dados)
    {
        try {
            $this->log("🛒 EMISSÃO DE NFC-e (Modelo 65)");

            // Normalizar estrutura dos dados
            if (isset($dados['nfce'])) {
                $this->log("🔧 Normalizando estrutura do JSON com objeto 'nfce'");
                $dados['numero'] = $dados['nfce']['numero'] ?? $dados['numero'] ?? '1';
                $dados['serie'] = $dados['nfce']['serie'] ?? $dados['serie'] ?? '001';
                // Para NFC-e, SEMPRE usar data/hora atual para evitar erro 704
                $dados['data_emissao'] = date('Y-m-d H:i:s');
                $this->log("📅 Data de emissão definida como AGORA: " . $dados['data_emissao']);
            }

            // Criar estrutura de diretórios
            $this->criarEstruturaDiretorios($dados['empresa']['cnpj']);

            // Gerar XML da NFC-e
            $xml = $this->gerarXML($dados);

            // Assinar XML
            $xmlAssinado = $this->assinarXML($xml, $dados['empresa']);

            // Enviar para SEFAZ
            $resultado = $this->enviarParaSEFAZ($xmlAssinado, $dados);

            if ($resultado['success']) {
                // Usar XML protocolado se disponível
                $xmlParaPDF = $resultado['xml_protocolado'] ?? $xmlAssinado;

                // Salvar XML protocolado
                if ($resultado['xml_protocolado']) {
                    $xmlPath = $this->salvarXML($resultado['xml_protocolado'], $dados);
                } else {
                    $xmlPath = $this->salvarXML($xmlAssinado, $dados);
                }

                // Gerar PDF (DANFE cupom)
                $pdfPath = $this->gerarPDF($dados, $xmlParaPDF, $resultado['protocolo'] ?? null);

                return [
                    'success' => true,
                    'numero' => $dados['numero'],
                    'serie' => $dados['serie'],
                    'chave_acesso' => $resultado['chave_acesso'],
                    'protocolo' => $resultado['protocolo'],
                    'cStat' => $resultado['cStat'] ?? null,
                    'xml_path' => $xmlPath,
                    'pdf_path' => $pdfPath,
                    'data_emissao' => $dados['data_emissao'],
                    'valor_total' => array_sum(array_column($dados['itens'], 'valor_total')),
                    'message' => 'NFC-e emitida com sucesso'
                ];
            } else {
                return [
                    'success' => false,
                    'chave_acesso' => $resultado['chave_acesso'] ?? null,
                    'cStat' => $resultado['cStat'] ?? null,
                    'numero' => $dados['numero'],
                    'serie' => $dados['serie'],
                    'error' => $resultado['error']
                ];
            }
        } catch (\Exception $e) {
            $this->log("❌ ERRO na emissão: " . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Gera XML da NFC-e usando NFePHP
     */
    private function gerarXML($dados)
    {
        $this->log("🚀 GERANDO XML DA NFC-e (MODELO 65)");

        // Carregar certificado
        $certificadoPath = __DIR__ . "/../../certificados/empresas/{$dados['empresa']['cnpj']}/{$dados['empresa']['cnpj']}.pfx";

        if (!file_exists($certificadoPath)) {
            throw new \Exception("Certificado não encontrado: {$certificadoPath}");
        }

        $configCertificado = require __DIR__ . '/../../config_certificado.php';
        $certificado = \App\Core\CertificateHelper::loadPfx($certificadoPath, $configCertificado['senha_certificado']);

        // Configuração para NFC-e
        $tpAmb = $dados['nfce']['ambiente'] ?? $dados['ambiente'] ?? 1; // 1=Produção, 2=Homologação

        $config = [
            "atualizacao" => date('Y-m-d H:i:s'),
            "tpAmb" => $tpAmb,
            "razaosocial" => $dados['empresa']['nome'],
            "cnpj" => preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']),
            "siglaUF" => $dados['empresa']['estado'],
            "schemes" => "PL_009_V4",
            "versao" => '4.00',
            "tokenIBPT" => $dados['nfce']['token'] ?? $dados['token'] ?? "AAAAAAA",
            "CSC" => $dados['empresa']['csc'] ?? '',
            "CSCid" => $dados['empresa']['csc_id'] ?? '000001'
        ];

        $configJson = json_encode($config);
        $tools = new Tools($configJson, $certificado);
        $tools->model(65); // Modelo 65 = NFC-e

        // Criar instância do Make
        $nfe = new \NFePHP\NFe\Make();

        // TAG infNFe (Raiz) - OBRIGATÓRIO
        $std = new \stdClass();
        $std->versao = '4.00';
        $std->Id = null; // Será gerado automaticamente
        $std->pk_nItem = null;
        $nfe->taginfNFe($std);

        // TAG ide (Identificação)
        $std = new \stdClass();
        $std->cUF = $this->getCodigoUF($dados['empresa']['estado']);
        $std->cNF = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT);
        $std->natOp = $dados['natureza_operacao'] ?? 'Venda de mercadorias';
        $std->mod = 65; // Modelo 65 = NFC-e
        $std->serie = intval($dados['serie']);
        $std->nNF = intval($dados['numero']);
        $std->dhEmi = date('Y-m-d\TH:i:sP', strtotime($dados['data_emissao']));
        $std->tpNF = 1; // 1 = Saída
        $std->idDest = 1; // 1 = Operação interna
        $std->cMunFG = $this->getCodigoMunicipio($dados['empresa']['cidade'], $dados['empresa']['estado']);
        $std->tpImp = 4; // 4 = DANFE NFC-e (cupom)
        $std->tpEmis = 1; // 1 = Emissão normal
        $std->tpAmb = $tpAmb; // 1 = Produção, 2 = Homologação
        $std->finNFe = 1; // 1 = NF-e normal
        $std->indFinal = 1; // 1 = Consumidor final (sempre para NFC-e)
        $std->indPres = 1; // 1 = Operação presencial
        $std->procEmi = 0; // 0 = Emissão própria
        $std->verProc = '1.0';

        $nfe->tagide($std);

        // TAG emit (Emitente)
        $std = new \stdClass();
        $std->xNome = $dados['empresa']['nome'];
        $std->xFant = $dados['empresa']['nome_fantasia'] ?? $dados['empresa']['nome'];
        $std->IE = preg_replace('/[^0-9]/', '', $dados['empresa']['inscricao_estadual']);
        $std->CRT = $dados['empresa']['regime_tributario'] ?? 1; // 1 = Simples Nacional
        $std->CNPJ = preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']);

        $nfe->tagemit($std);

        // TAG enderEmit (Endereço do emitente)
        $std = new \stdClass();
        $std->xLgr = $dados['empresa']['endereco'];
        $std->nro = $dados['empresa']['numero'];
        $std->xBairro = $dados['empresa']['bairro'];
        $std->cMun = $this->getCodigoMunicipio($dados['empresa']['cidade'], $dados['empresa']['estado']);
        $std->xMun = $dados['empresa']['cidade'];
        $std->UF = $dados['empresa']['estado'];
        $std->CEP = preg_replace('/[^0-9]/', '', $dados['empresa']['cep']);
        $std->cPais = '1058';
        $std->xPais = 'BRASIL';
        $std->fone = preg_replace('/[^0-9]/', '', $dados['empresa']['telefone'] ?? '');

        $nfe->tagenderEmit($std);

        // TAG dest (Destinatário) - OPCIONAL para NFC-e
        if (isset($dados['cliente'])) {
            $cliente = $dados['cliente'];

            // Verificar se tem CPF ou CNPJ
            $temCPF = isset($cliente['cpf']) && !empty($cliente['cpf']);
            $temCNPJ = isset($cliente['cnpj']) && !empty($cliente['cnpj']);

            if ($temCPF || $temCNPJ) {
                $std = new \stdClass();

                if ($temCPF) {
                    $std->CPF = preg_replace('/[^0-9]/', '', $cliente['cpf']);
                } else {
                    $std->CNPJ = preg_replace('/[^0-9]/', '', $cliente['cnpj']);
                }

                if (isset($cliente['nome'])) {
                    $std->xNome = $cliente['nome'];
                }

                $std->indIEDest = 9; // 9 = Não contribuinte

                $nfe->tagdest($std);

                // Endereço do destinatário (se informado)
                if (isset($cliente['endereco'])) {
                    $std = new \stdClass();
                    $std->xLgr = $cliente['endereco'];
                    $std->nro = $cliente['numero'] ?? 'S/N';
                    $std->xBairro = $cliente['bairro'] ?? 'Centro';
                    $std->cMun = $this->getCodigoMunicipio($cliente['cidade'] ?? $dados['empresa']['cidade'], $cliente['estado'] ?? $dados['empresa']['estado']);
                    $std->xMun = $cliente['cidade'] ?? $dados['empresa']['cidade'];
                    $std->UF = $cliente['estado'] ?? $dados['empresa']['estado'];
                    $std->CEP = preg_replace('/[^0-9]/', '', $cliente['cep'] ?? '00000000');
                    $std->cPais = '1058';
                    $std->xPais = 'BRASIL';

                    $nfe->tagenderDest($std);
                }
            }
        }

        // TAG det (Produtos/Itens)
        foreach ($dados['itens'] as $index => $item) {
            $nItem = $index + 1;

            // TAG prod (Produto)
            $std = new \stdClass();
            $std->item = $nItem;
            $std->cProd = $item['codigo'];
            $std->cEAN = 'SEM GTIN';
            $std->xProd = $item['descricao'];
            $std->NCM = $item['ncm'];
            $std->CFOP = $item['cfop'];
            $std->uCom = $item['unidade_comercial'];
            $std->qCom = $item['quantidade_comercial'];
            $std->vUnCom = number_format($item['valor_unitario'], 2, '.', '');
            $std->vProd = number_format($item['valor_total'], 2, '.', '');
            $std->cEANTrib = 'SEM GTIN';
            $std->uTrib = $item['unidade_comercial'];
            $std->qTrib = $item['quantidade_comercial'];
            $std->vUnTrib = number_format($item['valor_unitario'], 2, '.', '');
            $std->indTot = 1;

            $nfe->tagprod($std);

            // TAG imposto
            $std = new \stdClass();
            $std->item = $nItem;
            $std->vTotTrib = number_format($item['valor_total'] * 0.12, 2, '.', ''); // Estimativa de impostos

            $nfe->tagimposto($std);

            // ICMS
            $cstIcms = $item['cst_icms'] ?? '102';
            $origem = $item['origem'] ?? '0';

            $std = new \stdClass();
            $std->item = $nItem;
            $std->orig = $origem;
            $std->CSOSN = $cstIcms;

            // Para CSOSN 102, não precisa informar outros campos
            $nfe->tagICMSSN($std);

            // PIS
            $std = new \stdClass();
            $std->item = $nItem;
            $std->CST = '49'; // 49 = Outras operações de saída
            $std->vBC = '0.00';
            $std->pPIS = '0.00';
            $std->vPIS = '0.00';

            $nfe->tagPIS($std);

            // COFINS
            $std = new \stdClass();
            $std->item = $nItem;
            $std->CST = '49'; // 49 = Outras operações de saída
            $std->vBC = '0.00';
            $std->pCOFINS = '0.00';
            $std->vCOFINS = '0.00';

            $nfe->tagCOFINS($std);
        }

        // TAG total
        $totalProdutos = array_sum(array_column($dados['itens'], 'valor_total'));

        $std = new \stdClass();
        $std->vBC = '0.00';
        $std->vICMS = '0.00';
        $std->vICMSDeson = '0.00';
        $std->vFCP = '0.00';
        $std->vBCST = '0.00';
        $std->vST = '0.00';
        $std->vFCPST = '0.00';
        $std->vFCPSTRet = '0.00';
        $std->vProd = number_format($totalProdutos, 2, '.', '');
        $std->vFrete = '0.00';
        $std->vSeg = '0.00';
        $std->vDesc = number_format($dados['desconto'] ?? 0, 2, '.', '');
        $std->vII = '0.00';
        $std->vIPI = '0.00';
        $std->vIPIDevol = '0.00';
        $std->vPIS = '0.00';
        $std->vCOFINS = '0.00';
        $std->vOutro = '0.00';
        $std->vNF = number_format($totalProdutos - ($dados['desconto'] ?? 0), 2, '.', '');
        $std->vTotTrib = number_format($totalProdutos * 0.12, 2, '.', '');

        $nfe->tagICMSTot($std);

        // TAG transp (Transporte)
        $std = new \stdClass();
        $std->modFrete = 9; // 9 = Sem frete

        $nfe->tagtransp($std);

        // TAG pag (Pagamento) - OBRIGATÓRIO para NFC-e
        $pagamentos = $dados['pagamentos'] ?? [
            [
                'forma' => '01', // 01 = Dinheiro
                'valor' => $totalProdutos
            ]
        ];

        // Calcular troco total primeiro
        $troco = 0;
        foreach ($pagamentos as $pagamento) {
            if (isset($pagamento['troco']) && $pagamento['troco'] > 0) {
                $troco += $pagamento['troco'];
            }
        }

        // TAG pag (Pagamento) - tag pai
        $std = new \stdClass();
        if ($troco > 0) {
            $std->vTroco = number_format($troco, 2, '.', '');
        }
        $nfe->tagpag($std);

        // TAG detPag (Detalhamento do Pagamento) - tags filhas
        foreach ($pagamentos as $index => $pagamento) {
            $std = new \stdClass();
            $std->indPag = 0; // 0=Pagamento à Vista, 1=Pagamento a Prazo
            $std->tPag = $pagamento['forma']; // 01=Dinheiro, 02=Cheque, 03=Cartão Crédito, 04=Cartão Débito, etc.
            $std->vPag = number_format($pagamento['valor'], 2, '.', '');

            $nfe->tagdetPag($std);
        }

        // TAG infAdic (Informações Adicionais)
        if (isset($dados['informacoes_complementares'])) {
            $std = new \stdClass();
            $std->infCpl = $dados['informacoes_complementares'];

            $nfe->taginfAdic($std);
        }

        // TAG infRespTec (Responsável Técnico) - OBRIGATÓRIO desde NT 2019.001
        $std = new \stdClass();
        $std->CNPJ = $dados['responsavel_tecnico']['cnpj'] ?? '30305332000145'; // Systhema Tecnologia
        $std->xContato = $dados['responsavel_tecnico']['contato'] ?? 'Systhema Tecnologia';
        $std->email = $dados['responsavel_tecnico']['email'] ?? 'desenvolvimento@Systhema.com.br';
        $std->fone = $dados['responsavel_tecnico']['telefone'] ?? '81997102197';

        // Informações do software (CSRT e Hash são opcionais)
        if (isset($dados['responsavel_tecnico']['csrt'])) {
            $std->CSRT = $dados['responsavel_tecnico']['csrt'];
        }
        if (isset($dados['responsavel_tecnico']['id_csrt'])) {
            $std->idCSRT = $dados['responsavel_tecnico']['id_csrt'];
        }

        $nfe->taginfRespTec($std);

        // Gerar XML
        $xml = $nfe->getXML();
        $this->log("✅ XML da NFC-e gerado com sucesso");

        return $xml;
    }

    /**
     * Assinar XML com certificado digital
     */
    private function assinarXML($xml, $empresa)
    {
        $this->log("🔐 ASSINANDO XML DA NFC-e");

        $certificadoPath = __DIR__ . "/../../certificados/empresas/{$empresa['cnpj']}/{$empresa['cnpj']}.pfx";
        $configCertificado = require __DIR__ . '/../../config_certificado.php';
        $certificado = \App\Core\CertificateHelper::loadPfx($certificadoPath, $configCertificado['senha_certificado']);

        $config = [
            "atualizacao" => date('Y-m-d H:i:s'),
            "tpAmb" => 1,
            "razaosocial" => $empresa['nome'],
            "cnpj" => preg_replace('/[^0-9]/', '', $empresa['cnpj']),
            "siglaUF" => $empresa['estado'],
            "schemes" => "PL_009_V4",
            "versao" => '4.00',
            "CSC" => $empresa['csc'] ?? '',
            "CSCid" => $empresa['csc_id'] ?? '000001'
        ];

        $configJson = json_encode($config);
        $tools = new Tools($configJson, $certificado);
        $tools->model(65);

        $xmlAssinado = $tools->signNFe($xml);
        $this->log("✅ XML assinado com sucesso");

        return $xmlAssinado;
    }

    /**
     * Enviar para SEFAZ
     */
    private function enviarParaSEFAZ($xml, $dados)
    {
        $this->log("📤 ENVIANDO NFC-e PARA SEFAZ");

        $certificadoPath = __DIR__ . "/../../certificados/empresas/{$dados['empresa']['cnpj']}/{$dados['empresa']['cnpj']}.pfx";
        $configCertificado = require __DIR__ . '/../../config_certificado.php';
        $certificado = \App\Core\CertificateHelper::loadPfx($certificadoPath, $configCertificado['senha_certificado']);

        $config = [
            "atualizacao" => date('Y-m-d H:i:s'),
            "tpAmb" => 1,
            "razaosocial" => $dados['empresa']['nome'],
            "cnpj" => preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']),
            "siglaUF" => $dados['empresa']['estado'],
            "schemes" => "PL_009_V4",
            "versao" => '4.00',
            "CSC" => $dados['empresa']['csc'] ?? '',
            "CSCid" => $dados['empresa']['csc_id'] ?? '000001'
        ];

        $configJson = json_encode($config);
        $tools = new Tools($configJson, $certificado);
        $tools->model(65);

        // Gerar ID do lote
        $idLote = date('YmdHis');

        // Enviar com modo SÍNCRONO (indSinc = 1) para 1 NFC-e
        $response = $tools->sefazEnviaLote([$xml], $idLote, 1);

        $st = new Standardize($response);
        $std = $st->toStd();

        // Verificar resposta
        if ($std->cStat == 103) {
            // Assíncrono: consultar recibo
            $nRec = $std->infRec->nRec;
            sleep(3);
            $protocoloResponse = $tools->sefazConsultaRecibo($nRec);
            $st = new Standardize($protocoloResponse);
            $std = $st->toStd();
        } elseif ($std->cStat == 104) {
            // Síncrono: já processado
            $this->log("✅ Lote processado (síncrono)");
        } else {
            // Erro
            return [
                'success' => false,
                'chave_acesso' => $this->extrairChaveAcessoDoXML($xml),
                'cStat' => $std->cStat,
                'error' => "Rejeição: " . ($std->xMotivo ?? 'Erro desconhecido')
            ];
        }

        // Verificar autorização
        if (
            $std->cStat == 104 &&
            isset($std->protNFe->infProt->cStat) &&
            in_array($std->protNFe->infProt->cStat, [100, 150])
        ) {
            $protocoloNumero = $std->protNFe->infProt->nProt;
            $cStat = $std->protNFe->infProt->cStat;
            $chaveAcesso = $this->extrairChaveAcessoDoXML($xml);

            $this->log("✅ NFC-e autorizada! Protocolo: $protocoloNumero");

            // Criar XML protocolado
            $xmlProtocolado = $this->criarXMLProtocolado($xml, $std->protNFe);

            return [
                'success' => true,
                'chave_acesso' => $chaveAcesso,
                'protocolo' => $protocoloNumero,
                'cStat' => $cStat,
                'xml_protocolado' => $xmlProtocolado
            ];
        } else {
            // Rejeitada
            $cStat = $std->protNFe->infProt->cStat ?? $std->cStat;
            $motivo = $std->protNFe->infProt->xMotivo ?? $std->xMotivo ?? 'Erro desconhecido';

            return [
                'success' => false,
                'chave_acesso' => $this->extrairChaveAcessoDoXML($xml),
                'cStat' => $cStat,
                'error' => "NFe rejeitada [$cStat]: $motivo"
            ];
        }
    }

    /**
     * Criar XML protocolado
     */
    private function criarXMLProtocolado($xml, $protNFe)
    {
        // Remover declaração XML do XML assinado para evitar duplicação
        $xmlLimpo = preg_replace('/<\?xml[^>]*\?>\s*/i', '', $xml);

        $xmlProtocolado = '<?xml version="1.0" encoding="UTF-8"?>';
        $xmlProtocolado .= '<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">';
        $xmlProtocolado .= $xmlLimpo;
        $xmlProtocolado .= '<protNFe versao="4.00">';
        $xmlProtocolado .= '<infProt>';
        $xmlProtocolado .= '<tpAmb>' . $protNFe->infProt->tpAmb . '</tpAmb>';
        $xmlProtocolado .= '<verAplic>' . $protNFe->infProt->verAplic . '</verAplic>';
        $xmlProtocolado .= '<chNFe>' . $protNFe->infProt->chNFe . '</chNFe>';
        $xmlProtocolado .= '<dhRecbto>' . $protNFe->infProt->dhRecbto . '</dhRecbto>';
        $xmlProtocolado .= '<nProt>' . $protNFe->infProt->nProt . '</nProt>';
        $xmlProtocolado .= '<digVal>' . $protNFe->infProt->digVal . '</digVal>';
        $xmlProtocolado .= '<cStat>' . $protNFe->infProt->cStat . '</cStat>';
        $xmlProtocolado .= '<xMotivo>' . $protNFe->infProt->xMotivo . '</xMotivo>';
        $xmlProtocolado .= '</infProt>';
        $xmlProtocolado .= '</protNFe>';
        $xmlProtocolado .= '</nfeProc>';

        return $xmlProtocolado;
    }

    /**
     * Salvar XML
     */
    private function salvarXML($xml, $dados)
    {
        $chaveAcesso = $this->extrairChaveAcessoDoXML($xml);
        $cnpj = preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']);
        $anoMes = date('Y_m');

        $xmlPath = __DIR__ . "/../../arquivos/{$cnpj}/nfce/xml/{$anoMes}/assinados/{$chaveAcesso}.xml";
        file_put_contents($xmlPath, $xml);

        $this->log("✅ XML salvo: {$xmlPath}");

        return "/pontti_nfe/arquivos/{$cnpj}/nfce/xml/{$anoMes}/assinados/{$chaveAcesso}.xml";
    }

    /**
     * Gerar PDF (DANFE Cupom)
     */
    private function gerarPDF($dados, $xml, $protocolo)
    {
        $this->log("🖨️ GERANDO DANFCE (Cupom)");

        try {
            $chaveAcesso = $this->extrairChaveAcessoDoXML($xml);
            $cnpj = preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']);
            $anoMes = date('Y_m');

            $this->log("📄 Chave de acesso: {$chaveAcesso}");
            $this->log("📄 CNPJ: {$cnpj}");
            $this->log("📄 Tamanho do XML: " . strlen($xml) . " bytes");

            // Verificar se a classe Danfce existe
            if (!class_exists('NFePHP\DA\NFe\Danfce')) {
                $this->log("❌ Classe Danfce não encontrada!");
                return null;
            }

            // Criar DANFCE usando layout padrão da biblioteca NFePHP
            $this->log("📄 Instanciando Danfce (layout padrão da biblioteca)...");

            // Verificar se o XML é protocolado (nfeProc) ou simples (NFe)
            $xmlParaDanfce = $xml;
            if (strpos($xml, '<nfeProc') === false && strpos($xml, '<?xml') === false) {
                $xmlParaDanfce = '<?xml version="1.0" encoding="UTF-8"?>' . $xml;
            }

            $this->log("📄 Tipo de XML: " . (strpos($xmlParaDanfce, '<nfeProc') !== false ? 'Protocolado' : 'Simples'));

            // Verificar se existe logo (buscar logo.jpg ou {CNPJ}.jpg)
            $logoPath = __DIR__ . "/../../certificados/empresas/{$cnpj}/logo.jpg";
            if (!file_exists($logoPath)) {
                $logoPath = __DIR__ . "/../../certificados/empresas/{$cnpj}/{$cnpj}.jpg";
            }

            $logoBase64 = null;

            if (file_exists($logoPath)) {
                $this->log("📸 Logo encontrada: {$logoPath}");
                $logoContent = file_get_contents($logoPath);
                $logoBase64 = 'data:image/jpeg;base64,' . base64_encode($logoContent);
            } else {
                $this->log("📸 Logo não encontrada");
            }

            // Instanciar Danfce (layout padrão) com logo se existir
            if ($logoBase64) {
                $danfce = new Danfce($xmlParaDanfce, '', '', '', $logoBase64);
            } else {
                $danfce = new Danfce($xmlParaDanfce);
            }

            $this->log("📄 Renderizando PDF com layout padrão da biblioteca...");
            $pdf = $danfce->render();

            $this->log("📄 PDF renderizado: " . strlen($pdf) . " bytes");

            $pdfPath = __DIR__ . "/../../arquivos/{$cnpj}/nfce/pdf/{$anoMes}/emitidos/NFCe_{$chaveAcesso}.pdf";

            $pdfDir = dirname($pdfPath);
            if (!is_dir($pdfDir)) {
                mkdir($pdfDir, 0755, true);
            }

            file_put_contents($pdfPath, $pdf);

            $this->log("✅ DANFCE gerado com layout padrão: {$pdfPath}");

            return "/pontti_nfe/arquivos/{$cnpj}/nfce/pdf/{$anoMes}/emitidos/NFCe_{$chaveAcesso}.pdf";
        } catch (\Exception $e) {
            $this->log("❌ ERRO ao gerar DANFCE: " . $e->getMessage());
            $this->log("❌ Tipo: " . get_class($e));
            $this->log("❌ Arquivo: " . $e->getFile() . " - Linha: " . $e->getLine());
            $this->log("❌ Stack trace: " . $e->getTraceAsString());

            // Tentar fallback com PDF simples
            try {
                return $this->gerarPDFSimples($xml, $this->extrairChaveAcessoDoXML($xml), preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']), date('Y_m'), $dados);
            } catch (\Exception $e2) {
                $this->log("❌ ERRO no PDF simples também: " . $e2->getMessage());
                return null;
            }
        }
    }

    /**
     * Gerar PDF simples usando TCPDF (fallback)
     */
    private function gerarPDFSimples($xml, $chaveAcesso, $cnpj, $anoMes, $dados)
    {
        $this->log("📄 Gerando PDF simples com TCPDF...");

        try {
            // Parse XML para extrair dados
            $dom = new \DOMDocument();
            $dom->loadXML($xml);

            // Extrair informações
            $nNF = $dom->getElementsByTagName('nNF')->item(0)->nodeValue ?? 'N/A';
            $serie = $dom->getElementsByTagName('serie')->item(0)->nodeValue ?? 'N/A';
            $dhEmi = $dom->getElementsByTagName('dhEmi')->item(0)->nodeValue ?? '';
            $vNF = $dom->getElementsByTagName('vNF')->item(0)->nodeValue ?? '0.00';
            $vProd = $dom->getElementsByTagName('vProd')->item(0)->nodeValue ?? '0.00';
            $vDesc = $dom->getElementsByTagName('vDesc')->item(0)->nodeValue ?? '0.00';

            // Emitente
            $emitNode = $dom->getElementsByTagName('emit')->item(0);
            $xNomeEmit = 'N/A';
            $cnpjEmit = '';

            if ($emitNode) {
                $xNomeNode = $emitNode->getElementsByTagName('xNome')->item(0);
                $cnpjNode = $emitNode->getElementsByTagName('CNPJ')->item(0);
                $xNomeEmit = $xNomeNode ? $xNomeNode->nodeValue : 'N/A';
                $cnpjEmit = $cnpjNode ? $cnpjNode->nodeValue : '';
            }

            // Destinatário
            $destNode = $dom->getElementsByTagName('dest')->item(0);
            $nomeCliente = 'CONSUMIDOR NÃO IDENTIFICADO';
            $cpfCnpjCliente = '';

            if ($destNode) {
                $xNomeNode = $destNode->getElementsByTagName('xNome')->item(0);
                $nomeCliente = $xNomeNode ? $xNomeNode->nodeValue : 'CONSUMIDOR NÃO IDENTIFICADO';

                $cpfNode = $destNode->getElementsByTagName('CPF')->item(0);
                $cnpjNode = $destNode->getElementsByTagName('CNPJ')->item(0);
                $cpfCnpjCliente = $cpfNode ? $cpfNode->nodeValue : ($cnpjNode ? $cnpjNode->nodeValue : '');
            }

            // Protocolo
            $nProt = $dom->getElementsByTagName('nProt')->item(0)->nodeValue ?? 'N/A';

            // Informações Complementares (observações)
            $infCplNode = $dom->getElementsByTagName('infCpl')->item(0);
            $infCpl = $infCplNode ? $infCplNode->nodeValue : null;

            // Criar PDF com TCPDF (formato cupom 80mm) - LAYOUT MODERNO
            $pdf = new \TCPDF('P', 'mm', array(80, 297), true, 'UTF-8');
            $pdf->SetCreator('Pontti NFC-e System');
            $pdf->SetAuthor('Systhema Tecnologia');
            $pdf->SetTitle('DANFCE - NFC-e #' . $nNF);
            $pdf->setPrintHeader(false);
            $pdf->setPrintFooter(false);
            $pdf->SetMargins(3, 3, 3);
            $pdf->SetAutoPageBreak(true, 3);
            $pdf->AddPage();

            // Verificar se existe logo (buscar logo.jpg ou {CNPJ}.jpg)
            $logoPath = __DIR__ . "/../../certificados/empresas/{$cnpj}/logo.jpg";
            if (!file_exists($logoPath)) {
                $logoPath = __DIR__ . "/../../certificados/empresas/{$cnpj}/{$cnpj}.jpg";
            }

            $temLogo = file_exists($logoPath);

            // LOGO NO TOPO (se existir)
            if ($temLogo) {
                $this->log("📸 Logo encontrada: {$logoPath}");

                // Inserir logo centralizada - 20mm de largura
                $pdf->Image($logoPath, 30, 5, 20, 0, 'JPG', '', 'T', false, 300, 'C', false, false, 0, false, false, false);

                // Calcular altura da logo para ajustar posição do texto
                $imageSize = @getimagesize($logoPath);
                if ($imageSize) {
                    $alturaLogo = (20 / $imageSize[0]) * $imageSize[1]; // Proporção
                    $yPos = 5 + $alturaLogo + 3; // Logo + espaçamento
                } else {
                    $yPos = 18; // Fallback: posição fixa
                }
            } else {
                $this->log("📸 Logo não encontrada. Tentou:");
                $this->log("   - certificados/empresas/{$cnpj}/logo.jpg");
                $this->log("   - certificados/empresas/{$cnpj}/{$cnpj}.jpg");
                $yPos = 5;
            }

            // NOME DA EMPRESA (abaixo da logo)
            $pdf->SetY($yPos);
            $pdf->SetFont('helvetica', 'B', 10);
            $pdf->Cell(74, 5, $xNomeEmit, 0, 1, 'C');

            $pdf->SetFont('helvetica', '', 8);
            $pdf->Cell(74, 4, 'CNPJ: ' . $this->formatarCNPJ($cnpjEmit), 0, 1, 'C');

            // Linha separadora
            $pdf->Ln(2);
            $pdf->SetDrawColor(200, 200, 200);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // TIPO DE DOCUMENTO
            $pdf->SetFont('helvetica', 'B', 9);
            $pdf->SetFillColor(50, 50, 50);
            $pdf->SetTextColor(255, 255, 255);
            $pdf->Cell(74, 6, 'CUPOM FISCAL ELETRÔNICO - NFC-e', 0, 1, 'C', true);
            $pdf->SetTextColor(0, 0, 0);
            $pdf->Ln(2);

            // DADOS DO DOCUMENTO
            $pdf->SetFont('helvetica', '', 8);
            $pdf->Cell(25, 4, 'Número:', 0, 0, 'L');
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(49, 4, $nNF, 0, 1, 'L');

            $pdf->SetFont('helvetica', '', 8);
            $pdf->Cell(25, 4, 'Série:', 0, 0, 'L');
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(49, 4, $serie, 0, 1, 'L');

            $pdf->SetFont('helvetica', '', 8);
            $pdf->Cell(25, 4, 'Emissão:', 0, 0, 'L');
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(49, 4, date('d/m/Y H:i', strtotime($dhEmi)), 0, 1, 'L');

            $pdf->Ln(2);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // CLIENTE
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->SetFillColor(245, 245, 245);
            $pdf->Cell(74, 5, 'CLIENTE', 0, 1, 'L', true);
            $pdf->Ln(1);

            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->MultiCell(74, 4, $nomeCliente, 0, 'L');

            if ($cpfCnpjCliente) {
                $pdf->SetFont('helvetica', '', 8);
                $pdf->Cell(74, 4, 'CPF/CNPJ: ' . $this->formatarCPFCNPJ($cpfCnpjCliente), 0, 1, 'L');
            } else {
                $pdf->SetFont('helvetica', 'I', 7);
                $pdf->SetTextColor(120, 120, 120);
                $pdf->Cell(74, 4, '(Sem identificação)', 0, 1, 'L');
                $pdf->SetTextColor(0, 0, 0);
            }

            $pdf->Ln(2);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // ITENS (extrair do XML)
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(74, 4, 'PRODUTOS/SERVIÇOS', 0, 1, 'L');
            $pdf->Ln(1);

            $detNodes = $dom->getElementsByTagName('det');
            foreach ($detNodes as $detNode) {
                $xProdNode = $detNode->getElementsByTagName('xProd')->item(0);
                $qComNode = $detNode->getElementsByTagName('qCom')->item(0);
                $vUnComNode = $detNode->getElementsByTagName('vUnCom')->item(0);
                $vProdNode = $detNode->getElementsByTagName('vProd')->item(0);

                if ($xProdNode) {
                    $pdf->SetFont('helvetica', '', 7);
                    $pdf->MultiCell(74, 3, $xProdNode->nodeValue, 0, 'L');

                    $qtd = $qComNode ? $qComNode->nodeValue : '1';
                    $vUn = $vUnComNode ? $vUnComNode->nodeValue : '0';
                    $vTot = $vProdNode ? $vProdNode->nodeValue : '0';

                    $pdf->SetFont('helvetica', '', 7);
                    $linha = sprintf(
                        '%s x R$ %s = R$ %s',
                        number_format(floatval($qtd), 2, ',', '.'),
                        number_format(floatval($vUn), 2, ',', '.'),
                        number_format(floatval($vTot), 2, ',', '.')
                    );
                    $pdf->Cell(74, 3, $linha, 0, 1, 'R');
                    $pdf->Ln(1);
                }
            }

            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // TOTAIS
            $pdf->SetFont('helvetica', '', 8);
            $pdf->Cell(50, 4, 'Valor dos Produtos:', 0, 0, 'L');
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(24, 4, 'R$ ' . number_format(floatval($vProd), 2, ',', '.'), 0, 1, 'R');

            if (floatval($vDesc) > 0) {
                $pdf->SetFont('helvetica', '', 8);
                $pdf->Cell(50, 4, 'Desconto:', 0, 0, 'L');
                $pdf->SetFont('helvetica', 'B', 8);
                $pdf->Cell(24, 4, '- R$ ' . number_format(floatval($vDesc), 2, ',', '.'), 0, 1, 'R');
            }

            $pdf->Ln(1);
            $pdf->SetFillColor(240, 240, 240);
            $pdf->SetFont('helvetica', 'B', 10);
            $pdf->Cell(50, 6, 'VALOR TOTAL:', 0, 0, 'L', true);
            $pdf->Cell(24, 6, 'R$ ' . number_format(floatval($vNF), 2, ',', '.'), 0, 1, 'R', true);

            $pdf->Ln(2);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // FORMA DE PAGAMENTO
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(74, 4, 'FORMA DE PAGAMENTO', 0, 1, 'L');

            $detPagNodes = $dom->getElementsByTagName('detPag');
            foreach ($detPagNodes as $detPagNode) {
                $tPagNode = $detPagNode->getElementsByTagName('tPag')->item(0);
                $vPagNode = $detPagNode->getElementsByTagName('vPag')->item(0);

                if ($tPagNode && $vPagNode) {
                    $formaPag = $this->getFormaPagamentoNome($tPagNode->nodeValue);
                    $valorPag = $vPagNode->nodeValue;

                    $pdf->SetFont('helvetica', '', 8);
                    $pdf->Cell(50, 4, $formaPag, 0, 0, 'L');
                    $pdf->SetFont('helvetica', 'B', 8);
                    $pdf->Cell(24, 4, 'R$ ' . number_format(floatval($valorPag), 2, ',', '.'), 0, 1, 'R');
                }
            }

            $pdf->Ln(2);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // OBSERVAÇÕES (se houver) - CENTRALIZADO
            if ($infCpl) {
                $pdf->SetFont('helvetica', 'B', 7);
                $pdf->Cell(74, 3, 'OBSERVAÇÕES', 0, 1, 'C');
                $pdf->Ln(1);
                $pdf->SetFont('helvetica', '', 7);
                $pdf->MultiCell(74, 3, $infCpl, 0, 'C');
                $pdf->Ln(2);
                $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
                $pdf->Ln(2);
            }

            // QR CODE (tamanho reduzido: 35x35mm)
            $pdf->SetFont('helvetica', 'B', 8);
            $pdf->Cell(74, 4, 'CONSULTA VIA QR CODE', 0, 1, 'C');
            $pdf->Ln(2);

            // Gerar QR Code com a URL de consulta
            $urlQrCode = $this->gerarURLQRCode($chaveAcesso, $dados);

            $style = array(
                'border' => 0,
                'vpadding' => 'auto',
                'hpadding' => 'auto',
                'fgcolor' => array(0, 0, 0),
                'bgcolor' => array(255, 255, 255),
                'module_width' => 1,
                'module_height' => 1
            );

            // QR Code centralizado - 35mm (reduzido de 50mm)
            $pdf->write2DBarcode($urlQrCode, 'QRCODE,L', 22.5, $pdf->GetY(), 35, 35, $style, 'N');
            $pdf->Ln(37);

            // INFORMAÇÕES FISCAIS
            $pdf->SetFont('helvetica', 'B', 7);
            $pdf->Cell(74, 3, 'PROTOCOLO DE AUTORIZAÇÃO', 0, 1, 'C');
            $pdf->SetFont('helvetica', '', 7);
            $pdf->Cell(74, 3, $nProt, 0, 1, 'C');

            $pdf->Ln(2);
            $pdf->SetFont('helvetica', 'B', 7);
            $pdf->Cell(74, 3, 'CHAVE DE ACESSO', 0, 1, 'C');
            $pdf->SetFont('courier', '', 6);
            $pdf->MultiCell(74, 3, chunk_split($chaveAcesso, 4, ' '), 0, 'C');

            $pdf->Ln(2);
            $pdf->Line(5, $pdf->GetY(), 75, $pdf->GetY());
            $pdf->Ln(2);

            // RODAPÉ
            $pdf->SetFont('helvetica', '', 7);
            $pdf->MultiCell(74, 3, 'Consulte pela chave de acesso em:', 0, 'C');
            $pdf->SetFont('helvetica', 'B', 7);
            $pdf->Cell(74, 3, 'www.nfce.fazenda.gov.br', 0, 1, 'C');

            $pdf->Ln(3);
            $pdf->SetFont('helvetica', 'B', 7);
            $pdf->SetTextColor(0, 0, 0);
            $pdf->Cell(74, 4, 'Mobbis - www.pontti.com.br', 0, 1, 'C');
            $pdf->SetTextColor(0, 0, 0);

            $pdf->writeHTML('', true, false, true, false, '');

            $pdfContent = $pdf->Output('', 'S');

            $pdfPath = __DIR__ . "/../../arquivos/{$cnpj}/nfce/pdf/{$anoMes}/emitidos/NFCe_{$chaveAcesso}.pdf";

            $pdfDir = dirname($pdfPath);
            if (!is_dir($pdfDir)) {
                mkdir($pdfDir, 0755, true);
            }

            file_put_contents($pdfPath, $pdfContent);

            $this->log("✅ PDF simples gerado: {$pdfPath}");

            return "/pontti_nfe/arquivos/{$cnpj}/nfce/pdf/{$anoMes}/emitidos/NFCe_{$chaveAcesso}.pdf";
        } catch (\Exception $e) {
            $this->log("❌ ERRO ao gerar PDF simples: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Extrair chave de acesso do XML
     */
    private function extrairChaveAcessoDoXML($xml)
    {
        if (preg_match('/Id="NFe(\d{44})"/', $xml, $matches)) {
            return $matches[1];
        }
        return null;
    }

    /**
     * Obter código da UF
     */
    private function getCodigoUF($uf)
    {
        $ufs = [
            'AC' => 12,
            'AL' => 27,
            'AP' => 16,
            'AM' => 13,
            'BA' => 29,
            'CE' => 23,
            'DF' => 53,
            'ES' => 32,
            'GO' => 52,
            'MA' => 21,
            'MT' => 51,
            'MS' => 50,
            'MG' => 31,
            'PA' => 15,
            'PB' => 25,
            'PR' => 41,
            'PE' => 26,
            'PI' => 22,
            'RJ' => 33,
            'RN' => 24,
            'RS' => 43,
            'RO' => 11,
            'RR' => 14,
            'SC' => 42,
            'SP' => 35,
            'SE' => 28,
            'TO' => 17
        ];

        return $ufs[$uf] ?? 0;
    }

    /**
     * Obter código do município (IBGE)
     */
    private function getCodigoMunicipio($cidade, $uf)
    {
        // Tabela simplificada - em produção, usar base completa do IBGE
        $municipios = [
            'Recife' => 2611606,
            'Paulista' => 2610707,
            'São Paulo' => 3550308,
            'Rio de Janeiro' => 3304557
        ];

        return $municipios[$cidade] ?? 9999999;
    }

    /**
     * Formatar CNPJ
     */
    private function formatarCNPJ($cnpj)
    {
        $cnpj = preg_replace('/[^0-9]/', '', $cnpj);
        if (strlen($cnpj) == 14) {
            return substr($cnpj, 0, 2) . '.' . substr($cnpj, 2, 3) . '.' . substr($cnpj, 5, 3) . '/' . substr($cnpj, 8, 4) . '-' . substr($cnpj, 12, 2);
        }
        return $cnpj;
    }

    /**
     * Formatar CPF ou CNPJ
     */
    private function formatarCPFCNPJ($doc)
    {
        $doc = preg_replace('/[^0-9]/', '', $doc);

        if (strlen($doc) == 11) {
            // CPF
            return substr($doc, 0, 3) . '.' . substr($doc, 3, 3) . '.' . substr($doc, 6, 3) . '-' . substr($doc, 9, 2);
        } elseif (strlen($doc) == 14) {
            // CNPJ
            return $this->formatarCNPJ($doc);
        }

        return $doc;
    }

    /**
     * Gerar URL do QR Code da NFC-e
     */
    private function gerarURLQRCode($chaveAcesso, $dados)
    {
        // URL base de consulta da NFC-e por estado
        $urlsConsulta = [
            'PE' => 'http://nfce.sefaz.pe.gov.br/nfce-web/consultarNFCe'
        ];

        $uf = $dados['empresa']['estado'] ?? 'PE';
        $urlBase = $urlsConsulta[$uf] ?? 'http://www.nfce.fazenda.gov.br/consultarNFCe';

        // Construir URL do QR Code
        $urlQrCode = $urlBase . '?chNFe=' . $chaveAcesso;

        return $urlQrCode;
    }

    /**
     * Obter nome da forma de pagamento
     */
    private function getFormaPagamentoNome($codigo)
    {
        $formas = [
            '01' => 'Dinheiro',
            '02' => 'Cheque',
            '03' => 'Cartão de Crédito',
            '04' => 'Cartão de Débito',
            '05' => 'Crédito Loja',
            '10' => 'Vale Alimentação',
            '11' => 'Vale Refeição',
            '12' => 'Vale Presente',
            '13' => 'Vale Combustível',
            '15' => 'Boleto Bancário',
            '16' => 'Depósito Bancário',
            '17' => 'PIX',
            '18' => 'Transferência Bancária',
            '19' => 'Programa de Fidelidade',
            '90' => 'Sem Pagamento',
            '99' => 'Outros'
        ];

        return $formas[$codigo] ?? 'Outros';
    }

    /**
     * Cancelar NFC-e
     */
    public function cancelar($dados)
    {
        $this->log("❌ CANCELAMENTO DE NFC-e");

        try {
            $certificadoPath = __DIR__ . "/../../certificados/empresas/{$dados['empresa']['cnpj']}/{$dados['empresa']['cnpj']}.pfx";
            $configCertificado = require __DIR__ . '/../../config_certificado.php';
            $certificadoConteudo = file_get_contents($certificadoPath);
            $certificado = \App\Core\CertificateHelper::loadPfx($certificadoPath, $configCertificado['senha_certificado']);

            $config = [
                "atualizacao" => date('Y-m-d H:i:s'),
                "tpAmb" => 1,
                "razaosocial" => $dados['empresa']['nome'],
                "cnpj" => preg_replace('/[^0-9]/', '', $dados['empresa']['cnpj']),
                "siglaUF" => $dados['empresa']['estado'],
                "schemes" => "PL_009_V4",
                "versao" => '4.00'
            ];

            $configJson = json_encode($config);
            $tools = new Tools($configJson, $certificado);
            $tools->model(65);

            // Gerar evento de cancelamento
            $evento = $tools->sefazCancela(
                $dados['chave_acesso'],
                $dados['justificativa'],
                $dados['protocolo_autorizacao'] ?? null
            );

            $st = new Standardize($evento);
            $std = $st->toStd();

            if (isset($std->retEvento->infEvento->cStat) && $std->retEvento->infEvento->cStat == 135) {
                return [
                    'success' => true,
                    'chave_acesso' => $dados['chave_acesso'],
                    'message' => 'NFC-e cancelada com sucesso'
                ];
            } else {
                return [
                    'success' => false,
                    'error' => $std->retEvento->infEvento->xMotivo ?? 'Erro ao cancelar'
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}

