<?php
/**
 * VERSÃO: 2508181210	
 * Emissão NFe Focus v2 — PHP cURL
 * - JSON no corpo (sem Spyc / YAML)
 * - Basic Auth (token como usuário, senha vazia)
 * - Datas ISO-8601 com timezone
 * - Polling com timeout e backoff
 */
 
// Helper estilo "null coalesce" para PHP 5.4
function arr_get($arr, $key, $default = null) {
    return (is_array($arr) && isset($arr[$key])) ? $arr[$key] : $default;
}
 
register_shutdown_function(function () {
    $e = error_get_last();
    if ($e && in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        $log = '[' . date('c') . "] FATAL: {$e['message']} in {$e['file']}:{$e['line']}\n";
        @file_put_contents(__DIR__ . '/tmp/php_fatal.log', $log, FILE_APPEND);
        if (defined('DEBUG') && DEBUG) {
            // Em DEBUG, mostra o erro em texto puro (evita HTML corrompido)
            header('Content-Type: text/plain; charset=UTF-8');
            echo $log;
        }
    }
});

 
// DEBUG 
error_reporting(E_ALL);
ini_set('display_errors', 1);
date_default_timezone_set('America/Sao_Paulo');

// garante a pasta de logs/tmp
if (!is_dir(__DIR__ . '/tmp')) { @mkdir(__DIR__ . '/tmp', 0775, true); }

// PHP 7 compat: polyfill de str_starts_with
if (!function_exists('str_starts_with')) {
  function str_starts_with($haystack, $needle) {
    return strpos((string)$haystack, (string)$needle) === 0;
  }
}

define('DEBUG', true); // coloque false em produção
// 

require 'conectar.php';
// require_once "Spyc.php"; // <-- NÃO USAMOS MAIS

function to_iso8601_or_null($dt) {
    if (empty($dt)) return null;
    // Converte para "YYYY-MM-DDTHH:MM:SS-03:00"
    return date('c', strtotime($dt));
}

function focus_request($method, $url, $token, $bodyArrayOrNull = null, $extraHeaders = []) {
    $ch = curl_init($url);

    // DEBUG: rastreio do cURL em memória (sem depender de permissões em disco)
    $stderr = null;
    if (defined('DEBUG') && DEBUG) {
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        $stderr = fopen('php://temp', 'w+');
        curl_setopt($ch, CURLOPT_STDERR, $stderr);
    }

    $headers = array_merge(['Content-Type: application/json'], $extraHeaders);

    $opts = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST  => strtoupper($method),
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_HTTPAUTH       => CURLAUTH_BASIC,
        CURLOPT_USERPWD        => $token . ":",  // senha vazia
        CURLOPT_CONNECTTIMEOUT => 10,            // evita travar o worker do servidor
        CURLOPT_TIMEOUT        => 60,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_FAILONERROR    => false,         // queremos ver o corpo de erro
    ];

    if (!is_null($bodyArrayOrNull)) {
        $opts[CURLOPT_POSTFIELDS] = json_encode($bodyArrayOrNull, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }

    curl_setopt_array($ch, $opts);

    $body = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err  = curl_error($ch);

    // captura debug antes de fechar
    $curlDebug = '';
    if (defined('DEBUG') && DEBUG && is_resource($stderr)) {
        rewind($stderr);
        $curlDebug = stream_get_contents($stderr);
        fclose($stderr);
        @file_put_contents(__DIR__ . '/tmp/curl_debug.log', $curlDebug, FILE_APPEND);
    }

    curl_close($ch);

    return [$http, $body, $err];
}


// ---------- Entrada ----------
$chave = isset($_GET['chave']) ? trim($_GET['chave']) : '';
if ($chave === '') {
    http_response_code(400);
    die('Chave (ref) não informada.');
}

// ---------- Montagem dos arrays a partir do banco (mantive sua lógica) ----------
$pess = []; $dup = []; $fpgto = []; $vol = []; $item = []; $ref = [];

// Notas referenciadas
$rs_ref1 = $conn->query("select * from notas_referenciadas where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref1)){
    $ref[] = [
        "chave_nfe" => trim($row_ref["chave_nfe"]),
        "uf"        => trim($row_ref["uf"]),
        "mes"       => trim($row_ref["mes"]),
        "cnpj"      => trim($row_ref["cnpj"]),
        "modelo"    => trim($row_ref["modelo"]),
        "serie"     => trim($row_ref["serie"]),
        "numero"    => trim($row_ref["numero"])
    ];
}

// Pessoas autorizadas
$rs_ref1 = $conn->query("select * from pessoas_autorizadas where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref1)){
    $pess[] = [
        "cnpj" => trim($row_ref["cnpj"]),
        "cpf"  => trim($row_ref["cpf"])
    ];
}

// Volumes
$rs_ref = $conn->query("select * from volumes where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref)){
    $vol[] = [
        "quantidade"   => trim($row_ref["quantidade"]),
        "especie"      => trim($row_ref["especie"]),
        "marca"        => trim($row_ref["marca"]),
        "numero"       => trim($row_ref["numero"]),
        "peso_liquido" => trim($row_ref["peso_liquido"]),
        "peso_bruto"   => trim($row_ref["peso_bruto"]),
        "lacres"       => []
    ];
}

// Duplicatas
$rs_ref1 = $conn->query("select * from duplicatas where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref1)){
    $dup[] = [
        "numero"          => trim($row_ref["numero"]),
        "data_vencimento" => trim($row_ref["data_vencimento"]),
        "valor"           => trim($row_ref["valor"])
    ];
}

// Formas de pagamento
$rs_ref = $conn->query("select * from formas_pagamento where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref)){
    $fpgto[] = [
        "forma_pagamento"      => trim($row_ref["forma_pagamento"]),
        "valor_pagamento"      => trim($row_ref["valor_pagamento"]),
        "cnpj_credenciadora"   => trim($row_ref["cnpj_credenciadora"]),
        "bandeira_operadora"   => trim($row_ref["bandeira_operadora"]),
        "peso_liquido"         => trim($row_ref["peso_liquido"]),
        "numero_autorizadao"   => trim($row_ref["numero_autorizadao"])
    ];
}

// Itens
$rs_ref = $conn->query("select * from itens where chave = ?", [$chave]);
while($row_ref = $conn->fetch_assoc($rs_ref)){
    $item[] = [
        "numero_item"                        => trim($row_ref["numero_item"]),
        "codigo_produto"                     => trim($row_ref["codigo_produto"]),
        "codigo_barras_comercial"            => trim($row_ref["codigo_barras_comercial"]),
        "descricao"                          => trim($row_ref["descricao"]),
        "codigo_ncm"                         => trim($row_ref["codigo_ncm"]),
        "cfop"                               => trim($row_ref["cfop"]),
        "nves"                               => [], // seu código já deixava vazio
        "codigo_ex_tipi"                     => trim($row_ref["codigo_ex_tipi"]),
        "unidade_comercial"                  => trim($row_ref["unidade_comercial"]),
        "quantidade_comercial"               => trim($row_ref["quantidade_comercial"]),
        "valor_unitario_comercial"           => trim($row_ref["valor_unitario_comercial"]),
        "valor_bruto"                        => trim($row_ref["valor_bruto"]),
        "codigo_barras_tributavel"           => trim($row_ref["codigo_barras_tributavel"]),
        "unidade_tributavel"                 => trim($row_ref["unidade_tributavel"]),
        "quantidade_tributavel"              => trim($row_ref["quantidade_tributavel"]),
        "valor_unitario_tributavel"          => trim($row_ref["valor_unitario_tributavel"]),
        "valor_frete"                        => trim($row_ref["valor_frete"]),
        "valor_outras_despesas"              => trim($row_ref["valor_outras_despesas"]),
        "inclui_no_total"                    => trim($row_ref["inclui_no_total"]),
        "documentos_importacao"              => [],
        "detalhes_exportacao"                => [],
        "pedido_compra"                      => trim($row_ref["pedido_compra"]),
        "numero_item_pedido_compra"          => trim($row_ref["numero_item_pedido_compra"]),
        "icms_origem"                        => trim($row_ref["icms_origem"]),
        "icms_situacao_tributaria"           => trim($row_ref["icms_situacao_tributaria"]),
        "icms_modalidade_base_calculo"       => trim($row_ref["icms_modalidade_base_calculo"]),
        "icms_base_calculo"                  => trim($row_ref["icms_base_calculo"]),
        "icms_base_calculo_retido_st"        => trim($row_ref["icms_base_calculo_retido_st"]),
        "icms_reducao_base_calculo"          => trim($row_ref["icms_reducao_base_calculo"]),
        "icms_aliquota"                      => trim($row_ref["icms_aliquota"]),
        "icms_valor"                         => trim($row_ref["icms_valor"]),
        "icms_valor_retido_st"               => trim($row_ref["icms_valor_retido_st"]),
        "icms_valor_desonerado"              => trim($row_ref["icms_valor_desonerado"]),
        "icms_valor_operacao"                => trim($row_ref["icms_valor_operacao"]),
        "icms_percentual_diferimento"        => trim($row_ref["icms_percentual_diferimento"]),
        "icms_valor_diferido"                => trim($row_ref["icms_valor_diferido"]),
        "icms_motivo_desoneracao"            => trim($row_ref["icms_motivo_desoneracao"]),
        "icms_modalidade_base_calculo_st"    => trim($row_ref["icms_modalidade_base_calculo_st"]),
        "icms_margem_valor_adicionado_st"    => trim($row_ref["icms_margem_valor_adicionado_st"]),
        "icms_reducao_base_calculo_st"       => trim($row_ref["icms_reducao_base_calculo_st"]),
        "icms_base_calculo_st"               => trim($row_ref["icms_base_calculo_st"]),
        "icms_aliquota_st"                   => trim($row_ref["icms_aliquota_st"]),
        "icms_valor_st"                      => trim($row_ref["icms_valor_st"]),
        "ipi_situacao_tributaria"            => trim($row_ref["ipi_situacao_tributaria"]),
        "ipi_base_calculo"                   => trim($row_ref["ipi_base_calculo"]),
        "ipi_aliquota"                       => trim($row_ref["ipi_aliquota"]),
        "ipi_quantidade_total"               => trim($row_ref["ipi_quantidade_total"]),
        "ipi_valor_por_unidade_tributavel"   => trim($row_ref["ipi_valor_por_unidade_tributavel"]),
        "ipi_valor"                          => trim($row_ref["ipi_valor"]),
        "ipi_classe_enquadramento"           => trim($row_ref["ipi_classe_enquadramento"]),
        "ipi_cnpj_produtor"                  => trim($row_ref["ipi_cnpj_produtor"]),
        "ipi_codigo_selo_controle"           => trim($row_ref["ipi_codigo_selo_controle"]),
        "ipi_codigo_enquadramento_legal"     => trim($row_ref["ipi_codigo_enquadramento_legal"]),
        "pis_situacao_tributaria"            => trim($row_ref["pis_situacao_tributaria"]),
        "pis_base_calculo"                   => trim($row_ref["pis_base_calculo"]),
        "pis_aliquota_porcentual"            => trim($row_ref["pis_aliquota_porcentual"]),
        "pis_quantidade_vendida"             => trim($row_ref["pis_quantidade_vendida"]),
        "pis_aliquota_valor"                 => trim($row_ref["pis_aliquota_valor"]),
        "pis_valor"                           => trim($row_ref["pis_valor"]),
        "pis_base_calculo_st"                => trim($row_ref["pis_base_calculo_st"]),
        "pis_quantidade_vendida_st"          => trim($row_ref["pis_quantidade_vendida_st"]),
        "pis_aliquota_valor_st"              => trim($row_ref["pis_aliquota_valor_st"]),
        "pis_valor_st"                       => trim($row_ref["pis_valor_st"]),
        "cofins_situacao_tributaria"         => trim($row_ref["cofins_situacao_tributaria"]),
        "cofins_base_calculo"                => trim($row_ref["cofins_base_calculo"]),
        "cofins_aliquota_porcentual"         => trim($row_ref["cofins_aliquota_porcentual"]),
        "cofins_quantidade_vendida"          => trim($row_ref["cofins_quantidade_vendida"]),
        "cofins_aliquota_valor"              => trim($row_ref["cofins_aliquota_valor"]),
        "cofins_valor"                       => trim($row_ref["cofins_valor"]),
        "cofins_base_calculo_st"             => trim($row_ref["cofins_base_calculo_st"]),
        "cofins_aliquota_porcentual_st"      => trim($row_ref["cofins_aliquota_porcentual_st"]),
        "cofins_quantidade_vendida_st"       => trim($row_ref["cofins_quantidade_vendida_st"]),
        "cofins_aliquota_valor_st"           => trim($row_ref["cofins_aliquota_valor_st"]),
        "cofins_valor_st"                    => trim($row_ref["cofins_valor_st"]),
        "percentual_devolvido"               => trim($row_ref["percentual_devolvido"]),
        "valor_ipi_devolvido"                => trim($row_ref["valor_ipi_devolvido"])
    ];
}

// Nota
$rs_nfe = $conn->query("select * from notas where chave = ?", [$chave]);
$row = $conn->fetch_assoc($rs_nfe);

// Licença (tokens)
$rs_licenca = $conn->query("select * from licencas where id_licencas = ?", [$row["id_licencas"]]);
$licenca = $conn->fetch_assoc($rs_licenca);

if (!$row) {
    http_response_code(400);
    die('Nota não encontrada para a chave informada.');
}
if (!$licenca) {
    http_response_code(400);
    die('Licença não encontrada para a nota.');
}

// Ambiente
$tp = isset($_GET['tp']) ? $_GET['tp'] : '';
$ambHomolog = ($tp === 'H');

$BASE  = $ambHomolog ? 'https://homologacao.focusnfe.com.br' : 'https://api.focusnfe.com.br';
$TOKEN = $ambHomolog ? $licenca["token_homologacao"] : $licenca["token"];

// Nome em homologação
$nomeDest = $ambHomolog
    ? "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"
    : trim($row['nome_destinatario']);

// Montagem JSON NFe (v2)
$nota = [
    "natureza_operacao"                            => trim($row["natureza_operacao"]),
    "forma_pagamento"                              => trim($row["forma_pagamento"]),
    "data_emissao"                                 => to_iso8601_or_null($row["data_emissao"]),
    "data_entrada_saida"                           => to_iso8601_or_null($row["data_entrada_saida"]),
    "tipo_documento"                               => trim($row["tipo_documento"]),
    "local_destino"                                => trim($row["local_destino"]),
    "finalidade_emissao"                           => trim($row["finalidade_emissao"]),
    "consumidor_final"                             => trim($row["consumidor_final"]),
    "presenca_comprador"                           => trim($row["presenca_comprador"]),
    "cnpj_emitente"                                => trim($row['cnpj_emitente']),
    "nome_emitente"                                => trim($row["nome_emitente"]),
    "nome_fantasia_emitente"                       => trim($row["nome_fantasia_emitente"]),
    "logradouro_emitente"                          => trim($row["logradouro_emitente"]),
    "numero_emitente"                              => trim($row["numero_emitente"]),
    "complemento_emitente"                         => trim($row["complemento_emitente"]),
    "bairro_emitente"                              => trim($row["bairro_emitente"]),
    "municipio_emitente"                           => trim($row["municipio_emitente"]),
    "uf_emitente"                                  => trim($row["uf_emitente"]),
    "cep_emitente"                                 => trim($row["cep_emitente"]),
    "telefone_emitente"                            => trim($row["telefone_emitente"]),
    "inscricao_estadual_st_emitente"               => trim($row["inscricao_estadual_st_emitente"]),
    "inscricao_municipal_emitente"                 => trim($row["inscricao_municipal_emitente"]),
    "regime_tributario_emitente"                   => trim($row["regime_tributario_emitente"]),
    "cnpj_destinatario"                            => trim($row["cnpj_destinatario"]),
    "cpf_destinatario"                             => trim($row["cpf_destinatario"]),
    "id_estrangeiro_destinatario"                  => trim($row["id_estrangeiro_destinatario"]),
    "nome_destinatario"                            => $nomeDest,
    "logradouro_destinatario"                      => trim($row["logradoura_destinatario"]),
    "numero_destinatario"                          => trim($row["numero_destinatario"]),
    "complemento_destinatario"                     => trim($row["complemento_destinatario"]),
    "bairro_destinatario"                          => trim($row["bairro_destinatario"]),
    "codigo_municipio_destinatario"                => trim($row["codigo_municipio_destinatario"]),
    "municipio_destinatario"                       => trim($row["municipio_destinatario"]),
    "uf_destinatario"                              => trim($row["uf_destinatario"]),
    "cep_destinatario"                             => trim($row["cep_destinatario"]),
    "pais_destinatario"                            => trim($row["pais_destinatario"]),
    "telefone_destinatario"                        => trim($row["telefone_destinatario"]),
    "indicador_inscricao_estadual_destinatario"    => trim($row["indicador_inscricao_estadual_destinatario"]),
    "inscricao_estadual_destinatario"              => trim($row["inscricao_estadual_destinatario"]),
    "inscricao_suframa_destinatario"               => trim($row["inscricao_suframa_destinatario"]),
    "email_destinatario"                           => trim($row["email_destinatario"]),
    "inscricao_municipal_destinatario"             => trim($row["inscricao_municipal_destinatario"]),
    "cnpj_retirada"                                => trim($row["cnpj_retirada"]),
    "cpf_retirada"                                 => trim($row["cpf_retirada"]),
    "numero_retirada"                              => trim($row["numero_retirada"]),
    "complemento_retirada"                         => trim($row["complemento_retirada"]),
    "bairro_retirada"                              => trim($row["bairro_retirada"]),
    "codigo_municipio_retirada"                    => trim($row["codigo_municipio_retirada"]),
    "municipio_retirada"                           => trim($row["municipio_retirada"]),
    "uf_retirada"                                  => trim($row["uf_retirada"]),
    "cnpj_entrega"                                 => trim($row["cnpj_entrega"]),
    "cpf_entrega"                                  => trim($row["cpf_entrega"]),
    "logradouro_entrega"                           => trim($row["logradouro_entrega"]),
    "numero_entrega"                               => trim($row["numero_entrega"]),
    "complemento_entrega"                          => trim($row["complemento_entrega"]),
    "bairro_entrega"                               => trim($row["bairro_entrega"]),
    "codigo_municipio_entrega"                     => trim($row["codigo_municipio_entrega"]),
    "municipio_entrega"                            => trim($row["municipio_entrega"]),
    "uf_entrega"                                   => trim($row["uf_entrega"]),
    "icms_base_calculo"                            => trim($row["icms_base_calculo"]),
    "icms_valor_total"                             => trim($row["icms_valor_total"]),
    "icms_valor_total_desonerado"                  => trim($row["icms_valor_total_desonerado"]),
    "icms_base_calculo_st"                         => trim($row["icms_base_calculo_st"]),
    "icms_valor_total_st"                          => trim($row["icms_valor_total_st"]),
    "valor_produtos"                               => trim($row["valor_produtos"]),
    "valor_frete"                                  => trim($row["valor_frete"]),
    "valor_seguro"                                 => trim($row["valor_seguro"]),
    "valor_desconto"                               => trim($row["valor_desconto"]),
    "valor_total_ii"                               => trim($row["valor_total_ii"]),
    "valor_ipi"                                    => trim($row["valor_ipi"]),
    "valor_pis"                                    => trim($row["valor_pis"]),
    "valor_cofins"                                 => trim($row["valor_cofins"]),
    "valor_outras_despesas"                        => trim($row["valor_outras_despesas"]),
    "valor_total"                                  => trim($row["valor_total"]),
    "valor_total_servicos"                         => trim($row["valor_total_servicos"]),
    "data_prestacao_servico"                       => to_iso8601_or_null($row["data_prestacao_servico"]),
    "valor_total_deducao_base_calculo"             => trim($row["valor_total_deducao_base_calculo"]),
    "valor_total_outras_retencoes"                 => trim($row["valor_total_outras_retencoes"]),
    "valor_total_desconto_incondicionado"          => trim($row["valor_total_desconto_incondicionado"]),
    "valor_total_retencao_iss"                     => trim($row["valor_total_retencao_iss"]),
    "codigo_regime_especial_tributacao"            => trim($row["codigo_regime_especial_tributacao"]),
    "valor_retido_pis"                             => trim($row["valor_retido_pis"]),
    "valor_retido_cofins"                          => trim($row["valor_retido_cofins"]),
    "valor_retido_csll"                            => trim($row["valor_retido_csll"]),
    "base_calculo_irrf"                            => trim($row["base_calculo_irrf"]),
    "valor_retido_irrf"                            => trim($row["valor_retido_irrf"]),
    "prev_social_base_calculo"                     => trim($row["prev_social_base_calculo"]),
    "prev_social_valor_retido"                     => trim($row["prev_social_valor_retido"]),
    "modalidade_frete"                             => trim($row["modalidade_frete"]),
    "cnpj_transportador"                           => trim($row["cnpj_transportador"]),
    "cpf_transportador"                            => trim($row["cpf_transportador"]),
    "nome_transportador"                           => trim($row["nome_transportador"]),
    "inscricao_estadual_transportador"             => trim($row["inscricao_estadual_transportador"]),
    "endereco_transportador"                       => trim($row["endereco_transportador"]),
    "municipio_transportador"                      => trim($row["municipio_transportador"]),
    "uf_transportador"                             => trim($row["uf_transportador"]),
    "transporte_icms_servico"                      => trim($row["transporte_icms_servico"]),
    "transporte_icms_aliquota"                     => trim($row["transporte_icms_aliquota"]),
    "transporte_icms_valor"                        => trim($row["transporte_icms_valor"]),
    "transporte_icms_cfop"                         => trim($row["transporte_icms_cfop"]),
    "transporte_icms_codigo_municipio"             => trim($row["transporte_icms_codigo_municipio"]),
    "veiculo_placa"                                => trim($row["veiculo_placa"]),
    "veiculo_uf"                                   => trim($row["veiculo_uf"]),
    "veiculo_rntc"                                 => trim($row["veiculo_rntc"]),
    "veiculo_identificacao_vagao"                  => trim($row["veiculo_identificacao_vagao"]),
    "veiculo_identificacao_balsa"                  => trim($row["veiculo_identificacao_balsa"]),
    "numero_fatura"                                => trim($row["numero_fatura"]),
    "valor_original_fatura"                        => trim($row["valor_original_fatura"]),
    "valor_desconto_fatura"                        => trim($row["valor_desconto_fatura"]),
    "valor_liquido_fatura"                         => trim($row["valor_liquido_fatura"]),
    "informacoes_adicionais_contribuinte"          => trim($row["informacoes_adicionais_contribuinte"]),
    "uf_local_embarque"                            => trim($row["uf_local_embarque"]),
    "local_embarque"                               => trim($row["local_embarque"]),
    "local_despacho"                               => trim($row["local_despacho"]),
    "notas_referenciadas"                          => $ref,
    "pessoas_autorizadas"                          => $pess,
    "items"                                        => $item,
    "volumes"                                      => $vol,
    "duplicatas"                                   => $dup,
    "formas_pagamento"                             => $fpgto
];

// ==== SANITIZAÇÃO PARA ESQUEMA NFe (PHP 5.4) ====

// helper p/ limpar chaves vazias
function prune_empty_recursive(&$a) {
    foreach ($a as $k => $v) {
        if (is_array($v)) {
            prune_empty_recursive($v);
            if (empty($v)) unset($a[$k]);
        } else {
            if ($v === '' || $v === null) unset($a[$k]);
        }
    }
}

// 1) Renumera itens 1..N e limpa IPI por unidade quando incompleto
if (isset($nota['items']) && is_array($nota['items'])) {
    for ($i = 0; $i < count($nota['items']); $i++) {
        // numeração sequencial evita "det ... Duplicate key-sequence ['1']"
        $nota['items'][$i]['numero_item'] = $i + 1;

        // IPI por unidade (qUnid/vUnid): só envia se AMBOS vierem preenchidos
        $has_qUnid = isset($nota['items'][$i]['ipi_quantidade_total']) && trim($nota['items'][$i]['ipi_quantidade_total']) !== '';
        $has_vUnid = isset($nota['items'][$i]['ipi_valor_por_unidade_tributavel']) && trim($nota['items'][$i]['ipi_valor_por_unidade_tributavel']) !== '';
        if (!($has_qUnid && $has_vUnid)) {
            unset($nota['items'][$i]['ipi_quantidade_total']);
            unset($nota['items'][$i]['ipi_valor_por_unidade_tributavel']);
        }

        // remove numéricos vazios (evita tags com "")
        $numKeys = array(
            'icms_base_calculo','icms_aliquota','icms_valor','icms_base_calculo_retido_st','icms_valor_retido_st',
            'icms_reducao_base_calculo','icms_valor_desonerado','icms_percentual_diferimento','icms_valor_diferido',
            'icms_margem_valor_adicionado_st','icms_reducao_base_calculo_st','icms_base_calculo_st','icms_aliquota_st','icms_valor_st',
            'ipi_base_calculo','ipi_aliquota','ipi_valor',
            'pis_base_calculo','pis_aliquota_porcentual','pis_quantidade_vendida','pis_aliquota_valor','pis_valor',
            'pis_base_calculo_st','pis_quantidade_vendida_st','pis_aliquota_valor_st','pis_valor_st',
            'cofins_base_calculo','cofins_aliquota_porcentual','cofins_quantidade_vendida','cofins_aliquota_valor','cofins_valor',
            'cofins_base_calculo_st','cofins_aliquota_porcentual_st','cofins_quantidade_vendida_st','cofins_aliquota_valor_st','cofins_valor_st',
            'percentual_devolvido','valor_ipi_devolvido','valor_frete','valor_outras_despesas',
            'valor_unitario_comercial','valor_unitario_tributavel','valor_bruto','quantidade_comercial','quantidade_tributavel'
        );
        foreach ($numKeys as $k) {
            if (isset($nota['items'][$i][$k]) && trim($nota['items'][$i][$k]) === '') {
                unset($nota['items'][$i][$k]);
            }
        }
    }
}

// 2) id_estrangeiro_destinatario só se NÃO houver CNPJ/CPF
$temDestDoc = (isset($nota['cnpj_destinatario']) && trim($nota['cnpj_destinatario']) !== '') ||
              (isset($nota['cpf_destinatario'])  && trim($nota['cpf_destinatario'])  !== '');
if ($temDestDoc) {
    unset($nota['id_estrangeiro_destinatario']);
}

// 3) Remover RETIRADA se não houver CNPJ/CPF (ordem e obrigatoriedade do XSD)
$temRetiradaId = (isset($nota['cnpj_retirada']) && trim($nota['cnpj_retirada']) !== '') ||
                 (isset($nota['cpf_retirada'])  && trim($nota['cpf_retirada'])  !== '');
if (!$temRetiradaId) {
    foreach (array('cnpj_retirada','cpf_retirada','numero_retirada','complemento_retirada','bairro_retirada',
                   'codigo_municipio_retirada','municipio_retirada','uf_retirada') as $k) {
        if (isset($nota[$k])) unset($nota[$k]);
    }
}

// 4) Remover ENTREGA se não houver CNPJ/CPF
$temEntregaId = (isset($nota['cnpj_entrega']) && trim($nota['cnpj_entrega']) !== '') ||
                (isset($nota['cpf_entrega'])  && trim($nota['cpf_entrega'])  !== '');
if (!$temEntregaId) {
    foreach (array('cnpj_entrega','cpf_entrega','logradouro_entrega','numero_entrega','complemento_entrega',
                   'bairro_entrega','codigo_municipio_entrega','municipio_entrega','uf_entrega') as $k) {
        if (isset($nota[$k])) unset($nota[$k]);
    }
}

// 5) Transporte: só envia retTransp se houver CFOP
$temRetTransp = (isset($nota['transporte_icms_cfop']) && trim($nota['transporte_icms_cfop']) !== '');
if (!$temRetTransp) {
    foreach (array('transporte_icms_servico','transporte_icms_aliquota','transporte_icms_valor',
                   'transporte_icms_cfop','transporte_icms_codigo_municipio') as $k) {
        if (isset($nota[$k])) unset($nota[$k]);
    }
}

// 6) Totais: zeros quando vierem vazios (padrão '0.00')
$totKeys2 = array(
    'icms_base_calculo','icms_valor_total','icms_valor_total_desonerado','icms_base_calculo_st','icms_valor_total_st',
    'valor_produtos','valor_frete','valor_seguro','valor_desconto','valor_total_ii','valor_ipi','valor_pis',
    'valor_cofins','valor_outras_despesas','valor_total'
);
foreach ($totKeys2 as $k) {
    if (!isset($nota[$k]) || trim($nota[$k]) === '') {
        $nota[$k] = number_format(0, 2, '.', '');
    } else {
        $v = str_replace(',', '.', $nota[$k]);
        if (!is_numeric($v)) $v = 0;
        $nota[$k] = number_format($v + 0, 2, '.', '');
    }
}

// 7) Limpa quaisquer chaves vazias restantes
prune_empty_recursive($nota);


// (Opcional) salvar payload para auditoria
file_put_contents("tmp/nfe.json", json_encode($nota, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));




// ---------- AUTORIZAR ----------
$autorizarUrl = $BASE . "/v2/nfe?ref=" . urlencode($chave);
list($httpCode, $body, $curlErr) = focus_request('POST', $autorizarUrl, $TOKEN, $nota);

$conn->query("SELECT * FROM notas WHERE chave  = ?", [$chave]);
$row1 = $conn->fetch_assoc();


if ($httpCode == 202) {
    $conn->update("notas",
      ["tx_obs" => $row1['tx_obs']."<br>>>>> Transmitido em ".date('d/m/Y')],
      "chave = ?", [$chave]);
} else {
    $fail = $curlErr ?: $body;
    $conn->update("notas",
      ["tx_obs" => $row1['tx_obs']."<br>>>>> Falha em ".date('d/m/Y')." ".$fail],
      "chave = ?", [$chave]);

	if (defined('DEBUG') && DEBUG) {
		if (!defined('ENT_SUBSTITUTE')) define('ENT_SUBSTITUTE', 0);
		$httpStr = (string)$httpCode;
		$bodyStr = is_scalar($body) ? (string)$body : json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
		echo "HTTP: {$httpStr}<br>";
		echo "Body: " . htmlspecialchars($bodyStr, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . "<br>";
		@file_put_contents(__DIR__ . '/tmp/polling_last.json', $bodyStr);
	}
	
    exit; // <- crítico: não siga para o polling se não foi aceito
	
}


// ---------- CONSULTAR (polling) ----------
$consultarUrl = $BASE . "/v2/nfe/" . urlencode($chave);
$status = "processando_autorizacao";
$tentativas = 0;
$maxTentativas = 60;  // ~1 min
$espera = 1;          // segundos (pode fazer backoff)

while ($tentativas < $maxTentativas) {
    list($http, $bodyC, $errC) = focus_request('GET', $consultarUrl, $TOKEN, null);
    $resp = json_decode($bodyC, true);
	
	if (defined('DEBUG') && DEBUG) {
		if (!defined('ENT_SUBSTITUTE')) define('ENT_SUBSTITUTE', 0);
		$httpStr = (string)$http;
		$bodyStr = is_scalar($bodyC) ? (string)$bodyC : json_encode($bodyC, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
		echo "HTTP: {$httpStr}<br>";
		echo "Body: " . htmlspecialchars($bodyStr, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . "<br>";
		@file_put_contents(__DIR__ . '/tmp/polling_last.json', $bodyStr);
	}

    if ($http >= 400) {
        // Erros de consulta — mantém polling por alguns ciclos, mas loga
        $tentativas++;
        sleep($espera);
        continue;
    }

	$status = isset($resp['status']) ? $resp['status'] : 'desconhecido';
    if ($status === 'processando_autorizacao') {
        $tentativas++;
        sleep($espera);
        // backoff leve
        if ($espera < 3) $espera++;
        continue;
    }
    // Sai do loop quando não estiver mais processando
    break;
	
}

// ---------- TRATAMENTO FINAL ----------
if ($status === "erro_autorizacao") {
    $conn->query("SELECT * FROM notas WHERE chave = ?", [$chave]);
    $row = $conn->fetch_assoc();

	$mensagem = isset($resp['mensagem_sefaz']) ? $resp['mensagem_sefaz'] :
				(isset($resp['mensagem']) ? $resp['mensagem'] : 'erro na autorização');
    $obs = $row['tx_obs'] . "<br>>>> Erro - ".date("d/m/Y H:i:s")." - " . $mensagem;
    $conn->update("notas", ["tx_obs" => $obs, "st_nota" => "E"], "chave = ?", [$chave]);	

} elseif ($status === "autorizado") {
    $conn->query("SELECT * FROM notas WHERE chave = ?", [$chave]);
    $row = $conn->fetch_assoc();

    // A v2 pode retornar links diretos ou caminhos; tentamos ambos
	$danfe = isset($resp['link_danfe']) ? $resp['link_danfe']
			: (isset($resp['caminho_danfe']) ? $resp['caminho_danfe'] : null);
	if ($danfe && substr((string)$danfe, 0, 1) === '/') $danfe = $BASE . $danfe;

	$xml   = isset($resp['link_xml']) ? $resp['link_xml']
			: (isset($resp['caminho_xml_nota_fiscal']) ? $resp['caminho_xml_nota_fiscal'] : null);	
	if ($xml   && substr((string)$xml,   0, 1) === '/') $xml   = $BASE . $xml;

    $obs  = $row['tx_obs'] . "<br>>>> ".date("d/m/Y H:i:s")." - " . $status . " - " . ($ambHomolog ? "homologacao" : "producao");
    if ($danfe) $obs .= "<br><a href='".htmlspecialchars($danfe, ENT_QUOTES)."' target='_blank'>Arquivo DANFe</a>";
    if ($xml)   $obs .= "<br><a href='".htmlspecialchars($xml, ENT_QUOTES)."' target='_blank'>Arquivo XML</a>";	

    $conn->update("notas", ["tx_obs" => $obs, "st_nota" => $ambHomolog ? "N" : "F"], "chave = ?", [$chave]);
}


// Redireciona para a listagem
echo "<script>window.location.href = '../notas.php'</script>";

