<?php
namespace Modules\Fiscal\Services;

use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Tenant\TenantContext;
use PDO;
use Exception;
use DOMDocument;
use DOMXPath;

/**
 * Serviço para processamento de Notas Fiscais de Entrada
 */
class NFeEntradaService {
    private PDO $pdo;
    private string $tenantId;

    public function __construct() {
        $this->pdo = ConnectionManager::forTenant();
        $this->tenantId = TenantContext::getTenantId();
    }

    /**
     * Processa XML de NFe e extrai dados
     */
    public function processarXml(string $xmlContent): array {
        try {
            $dom = new DOMDocument();
            if (!@$dom->loadXML($xmlContent)) {
                throw new Exception('XML inválido ou malformado');
            }

            // Verificar namespace
            $xpath = new DOMXPath($dom);
            $xpath->registerNamespace('nfe', 'http://www.portalfiscal.inf.br/nfe');

            // Buscar NFeProc ou NFe
            $nfeProc = $xpath->query('//nfe:NFeProc | //NFeProc')->item(0);
            $nfe = $nfeProc ? $xpath->query('.//nfe:NFe | .//NFe', $nfeProc)->item(0) 
                            : $xpath->query('//nfe:NFe | //NFe')->item(0);

            if (!$nfe) {
                throw new Exception('Estrutura NFe não encontrada no XML');
            }

            $infNFe = $xpath->query('.//nfe:infNFe | .//infNFe', $nfe)->item(0);
            if (!$infNFe) {
                throw new Exception('Tag infNFe não encontrada');
            }

            // Extrair chave de acesso
            $chave = $infNFe->getAttribute('Id') ?? '';
            $chave = str_replace('NFe', '', $chave);
            if (strlen($chave) !== 44) {
                throw new Exception('Chave de acesso inválida no XML');
            }

            // Extrair dados do emitente
            $emit = $xpath->query('.//nfe:emit | .//emit', $infNFe)->item(0);
            $emitente = $this->extrairEmitente($xpath, $emit);

            // Extrair dados do destinatário
            $dest = $xpath->query('.//nfe:dest | .//dest', $infNFe)->item(0);
            $destinatario = $this->extrairDestinatario($xpath, $dest);

            // Extrair dados da nota
            $ide = $xpath->query('.//nfe:ide | .//ide', $infNFe)->item(0);
            $dadosNota = $this->extrairDadosNota($xpath, $ide);

            // Extrair valores totais
            $total = $xpath->query('.//nfe:total | .//total', $infNFe)->item(0);
            $valores = $this->extrairValores($xpath, $total);

            // Extrair itens
            $itens = [];
            $itemsNodes = $xpath->query('.//nfe:det | .//det', $infNFe);
            foreach ($itemsNodes as $itemNode) {
                $itens[] = $this->extrairItem($xpath, $itemNode);
            }

            // Extrair protocolo se existir
            $protNFe = $xpath->query('//nfe:protNFe | //protNFe', $nfeProc ?: $dom)->item(0);
            $protocolo = null;
            if ($protNFe) {
                $infProt = $xpath->query('.//nfe:infProt | .//infProt', $protNFe)->item(0);
                if ($infProt) {
                    $protocolo = $xpath->query('.//nfe:nProt | .//nProt', $infProt)->item(0)?->nodeValue;
                }
            }

            return [
                'chave_acesso' => $chave,
                'numero' => $dadosNota['numero'],
                'serie' => $dadosNota['serie'],
                'modelo' => $dadosNota['modelo'],
                'tipo_emissao' => $dadosNota['tipo_emissao'],
                'data_emissao' => $dadosNota['data_emissao'],
                'emitente' => $emitente,
                'destinatario' => $destinatario,
                'valores' => $valores,
                'itens' => $itens,
                'protocolo' => $protocolo,
                'xml_original' => $xmlContent
            ];
        } catch (Exception $e) {
            throw new Exception('Erro ao processar XML: ' . $e->getMessage());
        }
    }

    /**
     * Consulta NFe por chave de acesso usando SEFAZ
     */
    public function consultarPorChave(string $chave, string $ambiente = 'producao'): array {
        if (strlen($chave) !== 44 || !ctype_digit($chave)) {
            throw new Exception('Chave de acesso inválida. Deve ter 44 dígitos numéricos.');
        }

        try {
            $sefaService = new \Modules\Fiscal\Services\SEFAZService();
            $consulta = $sefaService->consultarNFe($chave, $ambiente);
            
            // Se autorizada, tentar baixar XML
            if ($consulta['status'] === 'autorizada' && !empty($consulta['xml'])) {
                try {
                    $dados = $this->processarXml($consulta['xml']);
                    return $dados;
                } catch (\Exception $e) {
                    // Se não conseguir processar XML, retornar dados da consulta
                    return [
                        'chave_acesso' => $chave,
                        'status' => $consulta['status'],
                        'protocolo' => $consulta['protocolo'],
                        'data_autorizacao' => $consulta['data_autorizacao'],
                        'mensagem' => 'Nota encontrada na SEFAZ. Use importação de XML para processar completamente.'
                    ];
                }
            }
            
            return [
                'chave_acesso' => $chave,
                'status' => $consulta['status'],
                'codigo_status' => $consulta['codigo_status'],
                'motivo' => $consulta['motivo'],
                'protocolo' => $consulta['protocolo']
            ];
        } catch (\Exception $e) {
            throw new Exception('Erro ao consultar SEFAZ: ' . $e->getMessage());
        }
    }

    /**
     * Salva nota fiscal de entrada no banco
     */
    public function salvarNota(array $dados, string $formaEntrada, ?int $fornecedorId = null): int {
        try {
            $this->pdo->beginTransaction();

            // Verificar se já existe
            $stmt = $this->pdo->prepare('SELECT id FROM nfe_entrada WHERE chave_acesso = ? AND tenant_id = ? LIMIT 1');
            $stmt->execute([$dados['chave_acesso'], $this->tenantId]);
            $existente = $stmt->fetch();

            if ($existente) {
                throw new Exception('Nota fiscal já cadastrada com esta chave de acesso');
            }

            // Buscar ou criar fornecedor
            if (!$fornecedorId && !empty($dados['emitente']['cnpj'])) {
                $fornecedorId = $this->buscarOuCriarFornecedor($dados['emitente']);
            }

            // Inserir nota
            $stmt = $this->pdo->prepare('INSERT INTO nfe_entrada 
                (tenant_id, chave_acesso, numero, serie, modelo, tipo_emissao,
                 emitente_cnpj, emitente_nome, emitente_ie, emitente_endereco,
                 destinatario_cnpj, destinatario_nome, destinatario_ie, destinatario_endereco,
                 data_emissao, data_entrada,
                 valor_produtos, valor_desconto, valor_frete, valor_seguro, valor_outras_despesas,
                 valor_total, valor_icms, valor_ipi, valor_pis, valor_cofins,
                 forma_entrada, fornecedor_id, protocolo_autorizacao, xml_original, ambiente, status)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');

            $stmt->execute([
                $this->tenantId,
                $dados['chave_acesso'],
                $dados['numero'],
                $dados['serie'],
                $dados['modelo'] ?? '55',
                $dados['tipo_emissao'] ?? 1,
                $dados['emitente']['cnpj'],
                $dados['emitente']['nome'],
                $dados['emitente']['ie'] ?? null,
                $dados['emitente']['endereco'] ?? null,
                $dados['destinatario']['cnpj'],
                $dados['destinatario']['nome'],
                $dados['destinatario']['ie'] ?? null,
                $dados['destinatario']['endereco'] ?? null,
                $dados['data_emissao'],
                $dados['valores']['produtos'] ?? 0,
                $dados['valores']['desconto'] ?? 0,
                $dados['valores']['frete'] ?? 0,
                $dados['valores']['seguro'] ?? 0,
                $dados['valores']['outras_despesas'] ?? 0,
                $dados['valores']['total'] ?? 0,
                $dados['valores']['icms'] ?? 0,
                $dados['valores']['ipi'] ?? 0,
                $dados['valores']['pis'] ?? 0,
                $dados['valores']['cofins'] ?? 0,
                $formaEntrada,
                $fornecedorId,
                $dados['protocolo'] ?? null,
                $dados['xml_original'] ?? null,
                'producao', // TODO: Detectar do XML
                'pendente'
            ]);

            $nfeId = (int)$this->pdo->lastInsertId();

            // Inserir itens
            if (!empty($dados['itens'])) {
                $itemStmt = $this->pdo->prepare('INSERT INTO nfe_entrada_itens
                    (nfe_entrada_id, numero_item, codigo_produto, codigo_barras, descricao, ncm, cfop, unidade,
                     quantidade, valor_unitario, valor_total, valor_desconto, valor_frete, valor_seguro, valor_outras_despesas,
                     icms_cst, icms_base_calculo, icms_aliquota, icms_valor,
                     ipi_cst, ipi_base_calculo, ipi_aliquota, ipi_valor,
                     pis_cst, pis_base_calculo, pis_aliquota, pis_valor,
                     cofins_cst, cofins_base_calculo, cofins_aliquota, cofins_valor, product_id)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');

                foreach ($dados['itens'] as $item) {
                    // Tentar mapear produto usando serviço de mapeamento
                    $mapeamentoService = new \Modules\Fiscal\Services\ProdutoMapeamentoService();
                    $productId = $mapeamentoService->mapearProduto($item);
                    
                    // Se não encontrado e auto_criar_fornecedor estiver ativo, criar produto
                    if (!$productId) {
                        try {
                            $stmt = $this->pdo->prepare('SELECT auto_criar_fornecedor, auto_criar_produto FROM nfe_entrada_deteccao WHERE tenant_id = ? AND ativo = 1 LIMIT 1');
                            $stmt->execute([$this->tenantId]);
                            $config = $stmt->fetch();
                            
                            if ($config && ($config['auto_criar_fornecedor'] || $config['auto_criar_produto'])) {
                                $productId = $mapeamentoService->criarProdutoSeNaoExistir($item, true);
                            }
                        } catch (\Exception $e) {
                            // Ignorar erro
                        }
                    } else {
                        // Atualizar produto com dados da nota
                        $mapeamentoService->atualizarProdutoComNota($productId, $item);
                    }

                    $itemStmt->execute([
                        $nfeId,
                        $item['numero_item'],
                        $item['codigo_produto'] ?? null,
                        $item['codigo_barras'] ?? null,
                        $item['descricao'],
                        $item['ncm'] ?? null,
                        $item['cfop'] ?? null,
                        $item['unidade'] ?? null,
                        $item['quantidade'],
                        $item['valor_unitario'],
                        $item['valor_total'],
                        $item['valor_desconto'] ?? 0,
                        $item['valor_frete'] ?? 0,
                        $item['valor_seguro'] ?? 0,
                        $item['valor_outras_despesas'] ?? 0,
                        $item['icms']['cst'] ?? null,
                        $item['icms']['base_calculo'] ?? 0,
                        $item['icms']['aliquota'] ?? 0,
                        $item['icms']['valor'] ?? 0,
                        $item['ipi']['cst'] ?? null,
                        $item['ipi']['base_calculo'] ?? 0,
                        $item['ipi']['aliquota'] ?? 0,
                        $item['ipi']['valor'] ?? 0,
                        $item['pis']['cst'] ?? null,
                        $item['pis']['base_calculo'] ?? 0,
                        $item['pis']['aliquota'] ?? 0,
                        $item['pis']['valor'] ?? 0,
                        $item['cofins']['cst'] ?? null,
                        $item['cofins']['base_calculo'] ?? 0,
                        $item['cofins']['aliquota'] ?? 0,
                        $item['cofins']['valor'] ?? 0,
                        $productId
                    ]);
                }
            }

            $this->pdo->commit();
            return $nfeId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Processa nota fiscal (integra com compras, estoque e financeiro)
     */
    public function processarNota(int $nfeId, bool $criarContaPagar = true): array {
        try {
            $this->pdo->beginTransaction();

            // Buscar nota
            $stmt = $this->pdo->prepare('SELECT * FROM nfe_entrada WHERE id = ? AND tenant_id = ? LIMIT 1');
            $stmt->execute([$nfeId, $this->tenantId]);
            $nfe = $stmt->fetch();

            if (!$nfe) {
                throw new Exception('Nota fiscal não encontrada');
            }

            if ($nfe['status'] === 'processada') {
                throw new Exception('Nota fiscal já foi processada');
            }

            // Buscar itens
            $stmt = $this->pdo->prepare('SELECT * FROM nfe_entrada_itens WHERE nfe_entrada_id = ? ORDER BY numero_item');
            $stmt->execute([$nfeId]);
            $itens = $stmt->fetchAll();

            // Criar invoice de compra
            $invoiceId = $this->criarInvoiceCompra($nfe, $itens);

            // Atualizar estoque
            $this->atualizarEstoque($itens, $nfe['numero'], $nfeId);

            // Criar conta a pagar se solicitado
            $contaPagarId = null;
            if ($criarContaPagar) {
                $contaPagarId = $this->criarContaPagar($nfe, $invoiceId);
            }

            // Atualizar status da nota
            $stmt = $this->pdo->prepare('UPDATE nfe_entrada SET status = ?, purchase_invoice_id = ? WHERE id = ?');
            $stmt->execute(['processada', $invoiceId, $nfeId]);

            $this->pdo->commit();

            return [
                'nfe_id' => $nfeId,
                'invoice_id' => $invoiceId,
                'conta_pagar_id' => $contaPagarId,
                'itens_processados' => count($itens)
            ];
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    // Métodos auxiliares privados
    private function extrairEmitente(DOMXPath $xpath, $emit): array {
        if (!$emit) return ['cnpj' => '', 'nome' => '', 'ie' => '', 'endereco' => ''];
        
        $cnpj = $xpath->query('.//nfe:CNPJ | .//CNPJ', $emit)->item(0)?->nodeValue ?? '';
        $nome = $xpath->query('.//nfe:xNome | .//xNome', $emit)->item(0)?->nodeValue ?? '';
        $ie = $xpath->query('.//nfe:IE | .//IE', $emit)->item(0)?->nodeValue ?? '';
        
        $ender = $xpath->query('.//nfe:enderEmit | .//enderEmit', $emit)->item(0);
        $endereco = '';
        if ($ender) {
            $logradouro = $xpath->query('.//nfe:xLgr | .//xLgr', $ender)->item(0)?->nodeValue ?? '';
            $numero = $xpath->query('.//nfe:nro | .//nro', $ender)->item(0)?->nodeValue ?? '';
            $bairro = $xpath->query('.//nfe:xBairro | .//xBairro', $ender)->item(0)?->nodeValue ?? '';
            $cidade = $xpath->query('.//nfe:xMun | .//xMun', $ender)->item(0)?->nodeValue ?? '';
            $uf = $xpath->query('.//nfe:UF | .//UF', $ender)->item(0)?->nodeValue ?? '';
            $cep = $xpath->query('.//nfe:CEP | .//CEP', $ender)->item(0)?->nodeValue ?? '';
            $endereco = trim("$logradouro, $numero - $bairro, $cidade/$uf - CEP: $cep");
        }
        
        return ['cnpj' => preg_replace('/\D/', '', $cnpj), 'nome' => $nome, 'ie' => $ie, 'endereco' => $endereco];
    }

    private function extrairDestinatario(DOMXPath $xpath, $dest): array {
        if (!$dest) return ['cnpj' => '', 'nome' => '', 'ie' => '', 'endereco' => ''];
        
        $cnpj = $xpath->query('.//nfe:CNPJ | .//CNPJ', $dest)->item(0)?->nodeValue ?? '';
        $cpf = $xpath->query('.//nfe:CPF | .//CPF', $dest)->item(0)?->nodeValue ?? '';
        $nome = $xpath->query('.//nfe:xNome | .//xNome', $dest)->item(0)?->nodeValue ?? '';
        $ie = $xpath->query('.//nfe:IE | .//IE', $dest)->item(0)?->nodeValue ?? '';
        
        $ender = $xpath->query('.//nfe:enderDest | .//enderDest', $dest)->item(0);
        $endereco = '';
        if ($ender) {
            $logradouro = $xpath->query('.//nfe:xLgr | .//xLgr', $ender)->item(0)?->nodeValue ?? '';
            $numero = $xpath->query('.//nfe:nro | .//nro', $ender)->item(0)?->nodeValue ?? '';
            $bairro = $xpath->query('.//nfe:xBairro | .//xBairro', $ender)->item(0)?->nodeValue ?? '';
            $cidade = $xpath->query('.//nfe:xMun | .//xMun', $ender)->item(0)?->nodeValue ?? '';
            $uf = $xpath->query('.//nfe:UF | .//UF', $ender)->item(0)?->nodeValue ?? '';
            $cep = $xpath->query('.//nfe:CEP | .//CEP', $ender)->item(0)?->nodeValue ?? '';
            $endereco = trim("$logradouro, $numero - $bairro, $cidade/$uf - CEP: $cep");
        }
        
        return ['cnpj' => preg_replace('/\D/', '', $cnpj ?: $cpf), 'nome' => $nome, 'ie' => $ie, 'endereco' => $endereco];
    }

    private function extrairDadosNota(DOMXPath $xpath, $ide): array {
        $numero = $xpath->query('.//nfe:nNF | .//nNF', $ide)->item(0)?->nodeValue ?? '';
        $serie = $xpath->query('.//nfe:serie | .//serie', $ide)->item(0)?->nodeValue ?? '';
        $modelo = $xpath->query('.//nfe:mod | .//mod', $ide)->item(0)?->nodeValue ?? '55';
        $tipoEmis = $xpath->query('.//nfe:tpEmis | .//tpEmis', $ide)->item(0)?->nodeValue ?? '1';
        $dhEmi = $xpath->query('.//nfe:dhEmi | .//dhEmi', $ide)->item(0)?->nodeValue ?? '';
        
        // Converter data
        $dataEmissao = null;
        if ($dhEmi) {
            try {
                $dt = new \DateTime($dhEmi);
                $dataEmissao = $dt->format('Y-m-d H:i:s');
            } catch (\Exception $e) {
                $dataEmissao = date('Y-m-d H:i:s');
            }
        }
        
        return ['numero' => $numero, 'serie' => $serie, 'modelo' => $modelo, 'tipo_emissao' => (int)$tipoEmis, 'data_emissao' => $dataEmissao];
    }

    private function extrairValores(DOMXPath $xpath, $total): array {
        $icmsTot = $xpath->query('.//nfe:ICMSTot | .//ICMSTot', $total)->item(0);
        if (!$icmsTot) return ['produtos' => 0, 'desconto' => 0, 'frete' => 0, 'seguro' => 0, 'outras_despesas' => 0, 'total' => 0, 'icms' => 0, 'ipi' => 0, 'pis' => 0, 'cofins' => 0];
        
        $produtos = $xpath->query('.//nfe:vProd | .//vProd', $icmsTot)->item(0)?->nodeValue ?? 0;
        $desconto = $xpath->query('.//nfe:vDesc | .//vDesc', $icmsTot)->item(0)?->nodeValue ?? 0;
        $frete = $xpath->query('.//nfe:vFrete | .//vFrete', $icmsTot)->item(0)?->nodeValue ?? 0;
        $seguro = $xpath->query('.//nfe:vSeg | .//vSeg', $icmsTot)->item(0)?->nodeValue ?? 0;
        $outras = $xpath->query('.//nfe:vOutro | .//vOutro', $icmsTot)->item(0)?->nodeValue ?? 0;
        $total = $xpath->query('.//nfe:vNF | .//vNF', $icmsTot)->item(0)?->nodeValue ?? 0;
        $icms = $xpath->query('.//nfe:vICMS | .//vICMS', $icmsTot)->item(0)?->nodeValue ?? 0;
        $ipi = $xpath->query('.//nfe:vIPI | .//vIPI', $icmsTot)->item(0)?->nodeValue ?? 0;
        $pis = $xpath->query('.//nfe:vPIS | .//vPIS', $icmsTot)->item(0)?->nodeValue ?? 0;
        $cofins = $xpath->query('.//nfe:vCOFINS | .//vCOFINS', $icmsTot)->item(0)?->nodeValue ?? 0;
        
        return [
            'produtos' => (float)str_replace(',', '.', $produtos),
            'desconto' => (float)str_replace(',', '.', $desconto),
            'frete' => (float)str_replace(',', '.', $frete),
            'seguro' => (float)str_replace(',', '.', $seguro),
            'outras_despesas' => (float)str_replace(',', '.', $outras),
            'total' => (float)str_replace(',', '.', $total),
            'icms' => (float)str_replace(',', '.', $icms),
            'ipi' => (float)str_replace(',', '.', $ipi),
            'pis' => (float)str_replace(',', '.', $pis),
            'cofins' => (float)str_replace(',', '.', $cofins)
        ];
    }

    private function extrairItem(DOMXPath $xpath, $itemNode): array {
        $prod = $xpath->query('.//nfe:prod | .//prod', $itemNode)->item(0);
        $imposto = $xpath->query('.//nfe:imposto | .//imposto', $itemNode)->item(0);
        
        $numeroItem = $itemNode->getAttribute('n') ?? '1';
        $codigo = $xpath->query('.//nfe:cProd | .//cProd', $prod)->item(0)?->nodeValue ?? '';
        $ean = $xpath->query('.//nfe:cEAN | .//cEAN', $prod)->item(0)?->nodeValue ?? '';
        $descricao = $xpath->query('.//nfe:xProd | .//xProd', $prod)->item(0)?->nodeValue ?? '';
        $ncm = $xpath->query('.//nfe:NCM | .//NCM', $prod)->item(0)?->nodeValue ?? '';
        $cfop = $xpath->query('.//nfe:CFOP | .//CFOP', $prod)->item(0)?->nodeValue ?? '';
        $unidade = $xpath->query('.//nfe:uCom | .//uCom', $prod)->item(0)?->nodeValue ?? '';
        $quantidade = $xpath->query('.//nfe:qCom | .//qCom', $prod)->item(0)?->nodeValue ?? 0;
        $valorUnitario = $xpath->query('.//nfe:vUnCom | .//vUnCom', $prod)->item(0)?->nodeValue ?? 0;
        $valorTotal = $xpath->query('.//nfe:vProd | .//vProd', $prod)->item(0)?->nodeValue ?? 0;
        
        // Impostos
        $icms = $this->extrairICMS($xpath, $imposto);
        $ipi = $this->extrairIPI($xpath, $imposto);
        $pis = $this->extrairPIS($xpath, $imposto);
        $cofins = $this->extrairCOFINS($xpath, $imposto);
        
        return [
            'numero_item' => (int)$numeroItem,
            'codigo_produto' => $codigo,
            'codigo_barras' => $ean,
            'descricao' => $descricao,
            'ncm' => $ncm,
            'cfop' => $cfop,
            'unidade' => $unidade,
            'quantidade' => (float)str_replace(',', '.', $quantidade),
            'valor_unitario' => (float)str_replace(',', '.', $valorUnitario),
            'valor_total' => (float)str_replace(',', '.', $valorTotal),
            'valor_desconto' => 0, // TODO: Extrair se existir
            'valor_frete' => 0,
            'valor_seguro' => 0,
            'valor_outras_despesas' => 0,
            'icms' => $icms,
            'ipi' => $ipi,
            'pis' => $pis,
            'cofins' => $cofins
        ];
    }

    private function extrairICMS(DOMXPath $xpath, $imposto): array {
        if (!$imposto) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        $icms = $xpath->query('.//nfe:ICMS/* | .//ICMS/*', $imposto)->item(0);
        if (!$icms) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        
        $cst = $xpath->query('.//nfe:CST | .//CST', $icms)->item(0)?->nodeValue ?? 
               $xpath->query('.//nfe:CSOSN | .//CSOSN', $icms)->item(0)?->nodeValue ?? null;
        $base = $xpath->query('.//nfe:vBC | .//vBC', $icms)->item(0)?->nodeValue ?? 0;
        $aliquota = $xpath->query('.//nfe:pICMS | .//pICMS', $icms)->item(0)?->nodeValue ?? 0;
        $valor = $xpath->query('.//nfe:vICMS | .//vICMS', $icms)->item(0)?->nodeValue ?? 0;
        
        return ['cst' => $cst, 'base_calculo' => (float)str_replace(',', '.', $base), 'aliquota' => (float)str_replace(',', '.', $aliquota), 'valor' => (float)str_replace(',', '.', $valor)];
    }

    private function extrairIPI(DOMXPath $xpath, $imposto): array {
        if (!$imposto) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        $ipi = $xpath->query('.//nfe:IPI/* | .//IPI/*', $imposto)->item(0);
        if (!$ipi) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        
        $cst = $xpath->query('.//nfe:CST | .//CST', $ipi)->item(0)?->nodeValue ?? null;
        $base = $xpath->query('.//nfe:vBC | .//vBC', $ipi)->item(0)?->nodeValue ?? 0;
        $aliquota = $xpath->query('.//nfe:pIPI | .//pIPI', $ipi)->item(0)?->nodeValue ?? 0;
        $valor = $xpath->query('.//nfe:vIPI | .//vIPI', $ipi)->item(0)?->nodeValue ?? 0;
        
        return ['cst' => $cst, 'base_calculo' => (float)str_replace(',', '.', $base), 'aliquota' => (float)str_replace(',', '.', $aliquota), 'valor' => (float)str_replace(',', '.', $valor)];
    }

    private function extrairPIS(DOMXPath $xpath, $imposto): array {
        if (!$imposto) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        $pis = $xpath->query('.//nfe:PIS/* | .//PIS/*', $imposto)->item(0);
        if (!$pis) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        
        $cst = $xpath->query('.//nfe:CST | .//CST', $pis)->item(0)?->nodeValue ?? null;
        $base = $xpath->query('.//nfe:vBC | .//vBC', $pis)->item(0)?->nodeValue ?? 0;
        $aliquota = $xpath->query('.//nfe:pPIS | .//pPIS', $pis)->item(0)?->nodeValue ?? 0;
        $valor = $xpath->query('.//nfe:vPIS | .//vPIS', $pis)->item(0)?->nodeValue ?? 0;
        
        return ['cst' => $cst, 'base_calculo' => (float)str_replace(',', '.', $base), 'aliquota' => (float)str_replace(',', '.', $aliquota), 'valor' => (float)str_replace(',', '.', $valor)];
    }

    private function extrairCOFINS(DOMXPath $xpath, $imposto): array {
        if (!$imposto) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        $cofins = $xpath->query('.//nfe:COFINS/* | .//COFINS/*', $imposto)->item(0);
        if (!$cofins) return ['cst' => null, 'base_calculo' => 0, 'aliquota' => 0, 'valor' => 0];
        
        $cst = $xpath->query('.//nfe:CST | .//CST', $cofins)->item(0)?->nodeValue ?? null;
        $base = $xpath->query('.//nfe:vBC | .//vBC', $cofins)->item(0)?->nodeValue ?? 0;
        $aliquota = $xpath->query('.//nfe:pCOFINS | .//pCOFINS', $cofins)->item(0)?->nodeValue ?? 0;
        $valor = $xpath->query('.//nfe:vCOFINS | .//vCOFINS', $cofins)->item(0)?->nodeValue ?? 0;
        
        return ['cst' => $cst, 'base_calculo' => (float)str_replace(',', '.', $base), 'aliquota' => (float)str_replace(',', '.', $aliquota), 'valor' => (float)str_replace(',', '.', $valor)];
    }

    private function buscarOuCriarFornecedor(array $emitente): ?int {
        $cnpj = preg_replace('/\D/', '', $emitente['cnpj']);
        if (empty($cnpj)) return null;
        
        // Buscar existente
        $stmt = $this->pdo->prepare('SELECT id FROM suppliers WHERE cnpj = ? LIMIT 1');
        $stmt->execute([$cnpj]);
        $fornecedor = $stmt->fetch();
        
        if ($fornecedor) {
            return (int)$fornecedor['id'];
        }
        
        // Criar novo
        $stmt = $this->pdo->prepare('INSERT INTO suppliers (nome, cnpj, email, contato) VALUES (?, ?, ?, ?)');
        $stmt->execute([$emitente['nome'], $cnpj, null, null]);
        return (int)$this->pdo->lastInsertId();
    }

    private function criarInvoiceCompra(array $nfe, array $itens): int {
        // Criar invoice de compra
        $stmt = $this->pdo->prepare('INSERT INTO purchase_invoices (numero, fornecedor_id, valor, data_emissao) VALUES (?, ?, ?, ?)');
        $stmt->execute([$nfe['numero'], $nfe['fornecedor_id'], $nfe['valor_total'], $nfe['data_emissao']]);
        $invoiceId = (int)$this->pdo->lastInsertId();
        
        // Inserir itens
        $itemStmt = $this->pdo->prepare('INSERT INTO purchase_invoice_items (invoice_id, product_id, quantidade, preco, total) VALUES (?, ?, ?, ?, ?)');
        foreach ($itens as $item) {
            $itemStmt->execute([
                $invoiceId,
                $item['product_id'] ?? null,
                $item['quantidade'],
                $item['valor_unitario'] ?? ($item['valor_total'] / $item['quantidade']),
                $item['valor_total']
            ]);
        }
        
        return $invoiceId;
    }

    private function atualizarEstoque(array $itens, string $numeroNota, int $nfeId): void {
        $movStmt = $this->pdo->prepare('INSERT INTO inventory_movements (product_id, tipo, quantidade, motivo, stock_before, stock_after, origin_type, origin_id, origin_number) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
        $prodGet = $this->pdo->prepare('SELECT id, estoque FROM products WHERE id = ? LIMIT 1');
        $prodUpd = $this->pdo->prepare('UPDATE products SET estoque = ? WHERE id = ?');
        
        foreach ($itens as $item) {
            $productId = $item['product_id'] ?? null;
            if (!$productId) continue;
            
            $prodGet->execute([$productId]);
            $prod = $prodGet->fetch();
            if (!$prod) continue;
            
            $before = (float)($prod['estoque'] ?? 0);
            $after = $before + (float)($item['quantidade'] ?? 0);
            
            $prodUpd->execute([$after, $productId]);
            $movStmt->execute([
                $productId,
                'entrada_compra',
                (float)($item['quantidade'] ?? 0),
                'Entrada de Nota Fiscal',
                $before,
                $after,
                'nfe_entrada',
                $nfeId,
                $numeroNota
            ]);
        }
    }

    private function criarContaPagar(array $nfe, int $invoiceId): ?int {
        // Verificar se módulo Financeiro existe
        try {
            $stmt = $this->pdo->prepare('INSERT INTO contas_pagar 
                (descricao, valor, data_vencimento, fornecedor_id, origem_tipo, origem_id, status)
                VALUES (?, ?, ?, ?, ?, ?, ?)');
            
            $dataVencimento = date('Y-m-d', strtotime($nfe['data_emissao'] . ' +30 days'));
            $stmt->execute([
                "NF {$nfe['numero']} - {$nfe['emitente_nome']}",
                $nfe['valor_total'],
                $dataVencimento,
                $nfe['fornecedor_id'],
                'purchase_invoice',
                $invoiceId,
                'pendente'
            ]);
            
            return (int)$this->pdo->lastInsertId();
        } catch (\Exception $e) {
            // Tabela pode não existir
            return null;
        }
    }
}

