<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class FelInvoice_model extends CI_Model
{
    public function __construct()
    {
        parent::__construct();
    }

    /*
     * ==================================================
     * FLUJO REAL CORRECTO
     * ==================================================
     * 1️⃣ obtener venta
     * 2️⃣ obtener token FEL (certificar)
     * 3️⃣ obtener token NUC (consultar NIT)
     * 4️⃣ consultar NIT
     * 5️⃣ construir JSON
     * 6️⃣ certificar
     * 7️⃣ guardar
     * NUNCA certificar antes del NIT
     * ==================================================
     */
    public function emitirDesdeSale($reference_no, $nit, $tipo = 'FACT', $modo_prueba = true, $taxid = null, $username = null)
    {
        /*
         * ===============================
         * 1️⃣ OBTENER VENTA
         * ===============================
         */
        $sale = $this->db
            ->where('reference_no', $reference_no)
            ->get('sma_sales')
            ->row_array();

        if (!$sale) {
            throw new Exception('Venta no encontrada');
        }

        $items = $this->db
            ->where('sale_id', $sale['id'])
            ->get('sma_sale_items')
            ->result_array();

        /*
         * ===============================
         * 2️⃣ CONEXIÓN CERTIFICADOR
         * ===============================
         */
        $this->load->admin_model('Certificadores_model', 'cert');

        $conexion = $this->db
            ->where('sucursal_id', $sale['warehouse_id'])
            ->where('activo', 1)
            ->get('sma_clientes_certificador_conexion')
            ->row();

        if (!$conexion) {
            throw new Exception('No hay certificador activo');
        }

        $username    = $conexion->usuario;
        $taxid       = $conexion->nit;
        $certificador = $this->cert->get_certificador($conexion->certificador_id);

        /*
         * ===============================
         * 3️⃣ TOKENS (AMBOS)
         * ===============================
         */
        $tokenFEL = $this->cert->get_token_valido($certificador, $conexion);

        log_message('error', 'TOKEN FEL: ' . $tokenFEL);

        if (!$tokenFEL) {
            throw new Exception('No se pudo obtener token Digifact FEL');
        }

        /*
         * ===============================
         * 4️⃣ CONSULTAR NIT (ANTES DE TODO)
         * ===============================
         */
        if (strtoupper($nit) === 'CF') {
            // Obtener datos del cliente de la base de datos
            $cliente_db = $this->db
                ->select('vat_no, name, address, city as municipio, state as departamento, country as pais, postal_code')
                ->where('id', $sale['customer_id'])
                ->where('group_name', 'customer')
                ->get('sma_companies')
                ->row_array();

            if (!$cliente_db) {
                throw new Exception('Cliente CF no encontrado en la base de datos');
            }

            $cliente = $cliente_db; // Asignar directamente el array $cliente_db a $cliente
            $cliente['vat_no'] = 'CF'; // Establecer el NIT como CF
        } else {
            $tokenNUC = $this->cert->get_token_valido_nuc($certificador, $conexion);

            if (!$tokenNUC) {
                throw new Exception('No se pudo obtener token Digifact NUC');
            }

            $cliente = $this->consultarNitDigifact($nit, $tokenNUC, $username, $taxid);
            log_message('error', 'CLIENTE OBTENIDO: ' . json_encode($cliente));
        }

        /*
         * ===============================
         * 5️⃣ JSON
         * ===============================
         */
        // Obtener datos del emisor (biller)
        $biller = $this->db
            ->where('group_name', 'biller')
            ->get('sma_companies')
            ->row_array();

         if (!$biller) {
             throw new Exception('Datos del emisor (biller) no encontrados en la base de datos');
         }

        $json = $this->buildJsonDigifact($sale, $items, $cliente, $biller, $tipo);

        /*
         * ===============================
         * 6️⃣ CERTIFICAR
         * ===============================
         */
        if ($modo_prueba) {
            // Devolver el JSON y los datos del cliente para mostrar en el modal
            return [
                'cliente' => $cliente,
                'json' => json_encode($json, JSON_PRETTY_PRINT), // Devolver el JSON formateado
                'reference_no' => $reference_no,
                'taxid' => $taxid,
                'username' => $username,
            ];
        } else {
            $response = $this->sendDigifact($json, $tokenFEL, $taxid, $username);

           $res = $response['response'] ?? [];

log_message('error', 'RESPUESTA COMPLETA FEL: ' . print_r($res, true));


if (empty($res['authNumber'])) {
    throw new Exception('Certificador no devolvió authNumber (UUID)');
}

            /*
             * ===============================
             * 7️⃣ GUARDAR
             * ===============================
             */
           $current_user_id = $this->session->userdata('user_id');

$this->saveInvoice($sale, $cliente, $res, $tipo, $biller, $current_user_id);

return [
    'cliente' => $cliente,
    'uuid'    => $res['authNumber'], // UUID real
    'ticket'  => $sale['reference_no'],
];

        }
    }

    /*
     * ==================================================
     * CONSULTA NIT (100% IGUAL A DOC DIGIFACT)
     * ==================================================
     */
   private function consultarNitDigifact($nit, $token, $username, $taxid)
{
    $url = "https://felgtaws.digifact.com.gt/gt.com.apinuc/api/Shared"
        . "?TAXID=" . $taxid
        . "&DATA1=SHARED_GETINFONITcom"
        . "&DATA2=NIT|" . $nit
        . "&COUNTRY=GT"
        . "&USERNAME=" . $username;

    log_message('error', 'INFONIT URL: ' . $url);

    $headers = [
        "Authorization: " . $token, // SIN Bearer (NUC NO USA BEARER)
        "Content-Type: application/json",
    ];

    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_HTTPHEADER => $headers,
    ]);

    $result = curl_exec($ch);

    if ($result === false) {
        log_message('error', 'CURL INFONIT: ' . curl_error($ch));
    }

    curl_close($ch);

    log_message('error', 'INFONIT RESPONSE: ' . $result);

    $data = json_decode($result, true);

    if (empty($data['RESPONSE'])) {
        throw new Exception('NIT no encontrado en SAT');
    }

    if ( ! is_array($data['RESPONSE']) || count($data['RESPONSE']) == 0) {
        throw new Exception('NIT no encontrado en el array de respuesta del SAT');
    }

    $r = $data['RESPONSE'][0]; // Accede al primer elemento del array RESPONSE

    // Usar el nombre tal cual lo devuelve la API
    $nombre = $r['NOMBRE'];

    return [
        'vat_no'  => $nit,
        'name'    => $nombre,
        'address' => $r['Direccion'],
        'municipio' => $r['MUNICIPIO'],
        'departamento' => $r['DEPARTAMENTO'],
        'pais' => 'GT',
        'postal_code' => '01001'
    ];
}

    /*
     * ==================================================
     * CERTIFICAR FEL
     * ==================================================
     */
  private function sendDigifact($json, $token, $taxid, $username)
{
    // Guardar log del JSON
    $this->logJson($json);

    log_message('error', '======= DATOS ENVIO FEL =======');
    log_message('error', 'TOKEN FEL: ' . $token);
    log_message('error', 'TAXID FEL: ' . $taxid);
    log_message('error', 'USERNAME FEL: ' . $username);

    $url = 'https://felgtaws.digifact.com.gt/gt.com.apinuc/api/v2/transform/nuc_json'
        . '?TAXID=' . $taxid
        . '&USERNAME=' . $username
        . '&FORMAT=XML';

    log_message('error', 'URL FINAL FEL: ' . $url);

    $ch = curl_init($url);

    $body = json_encode($json, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    if ($body === false) {
        log_message('error', 'ERROR JSON_ENCODE: ' . json_last_error_msg());
        return ['error' => 'JSON encode failed'];
    }

    $body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');

    log_message('error', 'BODY ENVIADO FEL: ' . $body);

    // 🔥 DEFINIMOS HEADERS FUERA DEL ARRAY
    $headers = [
        "Authorization: ".$token,
        "Content-Type: application/json; charset=utf-8",
        "Accept: application/json",
        "Content-Length: " . strlen($body)
    ];

    log_message('error', 'HEADERS FEL: ' . json_encode($headers));

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_CONNECTTIMEOUT => 30,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => $body,
        CURLINFO_HEADER_OUT => true
    ]);

    log_message('error', 'JSON FEL ENVIADO (FORMATEADO): ' . json_encode($json, JSON_PRETTY_PRINT));

    $result = curl_exec($ch);

    $sent_headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
    log_message('error', 'HEADERS REALES ENVIADOS POR CURL: ' . $sent_headers);

    if ($result === false) {
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        log_message('error', 'CURL ERROR FEL: ' . $errno . ' - ' . $error);
    }

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    log_message('error', 'HTTP CODE FEL: ' . $http_code);

    curl_close($ch);

    log_message('error', 'FEL RESPONSE: ' . $result);

    // 🔹 DEVOLVEMOS EL JSON FORMATEADO EN LA RESPUESTA TAMBIÉN
    return [
        'response' => json_decode($result, true),
        'json_sent' => $json // JSON original que se envió
    ];
}

private function buildJsonDigifact($sale, $items, $cliente, $biller, $tipo)
{
    $detalle = [];
    $total_impuestos = 0;
    $gran_total = 0;

    foreach ($items as $indice => $i) {
        $item_precio_unitario = floatval($i['unit_price']);
        $cantidad = floatval($i['quantity']);

        $item_total = round($item_precio_unitario * $cantidad, 6);

        // 🔥 Si el precio ya incluye IVA:
        $taxable_amount = round($item_total / 1.12, 6);
        $item_impuestos = round($taxable_amount * 0.12, 6);

        $detalle[] = [
            "Number" => strval($indice + 1),
            "Codes" => null,
            "Type" => "Bien",
            "Description" => $i['product_name'],
            "Qty" => number_format($i['quantity'], 4, '.', ''),
            "UnitOfMeasure" => "UND",
            "Price" => number_format($item_precio_unitario, 5, '.', ''),
            "Discounts" => null,
            "Taxes" => [
                "Tax" => [
                    [
                        "Code" => "1",
                        "Description" => "IVA",
                        "TaxableAmount" => number_format($taxable_amount, 6, '.', ''),
                        "Amount" => number_format($item_impuestos, 5, '.', '')
                    ]
                ]
            ],
            "Totals" => [
                "TotalItem" => number_format($item_total, 4, '.', '')
            ]
        ];

        $total_impuestos += $item_impuestos;
        $gran_total += $item_total;
    }

    $cantidad_letras = strtoupper(str_replace(',', '', numfmt_format_currency(numfmt_create('es_GT', NumberFormatter::SPELLOUT), $gran_total, 'GTQ'))) . " CON 00/100";

    $json = [
        "Version" => "1.00",
        "CountryCode" => "GT",
        "Header" => [
            "DocType" => $tipo,
            "IssuedDateTime" => date('Y-m-d\TH:i:s-06:00', strtotime($sale['date'])),
            "Currency" => "GTQ"
        ],
        "Seller" => [
            "TaxID" => $biller['vat_no'],
            "TaxIDAdditionalInfo" => [
                [
                    "Name" => "AfiliacionIVA",
                    "Data" => null,
                    "Value" => "GEN"
                ]
            ],
            "Name" => $biller['name'],
            "Contact" => [
                "EmailList" => [
                    "Email" => [
                        $biller['email'] ?? "correo@prueba.com"
                    ]
                ]
            ],
            "AdditionlInfo" => [
                [
  "Name" => "TipoFrase",
  "Data" => "0",
  "Value" => "0"
],
[
  "Name" => "Escenario",
  "Data" => "0",
  "Value" => "1"
],
[
  "Name" => "TipoFrase",
  "Data" => "1",
  "Value" => "1"
],
[
  "Name" => "Escenario",
  "Data" => "1",
  "Value" => "1"
],
[
  "Name" => "TipoFrase",
  "Data" => "2",
  "Value" => "2"
],
[
  "Name" => "Escenario",
  "Data" => "2",
  "Value" => "1"
],
            ],
            "BranchInfo" => [
                "Code" => "1",
                "Name" => $biller['name'],
                "AddressInfo" => [
                    "Address" => $biller['address'],
                    "City" => $biller['postal_code'],
                    "District" => $biller['city'],
                    "State" => $biller['state'],
                    "Country" => "GT"
                ]
            ]
        ],
        "Buyer" => [
            "TaxID" => $cliente['vat_no'],
            "Name" => $cliente['name'],
            "AddressInfo" => [
                "Address" => $cliente['address'],
                "City" => $cliente['postal_code'],
                "District" => $cliente['municipio'],
                "State" => $cliente['departamento'],
                "Country" => "GT"
            ],
            "Contact" => [
                "EmailList" => [
                    "Email" => [
                        $cliente['email'] ?? "correo@prueba.com"
                    ]
                ]
            ]
        ],
        "ThirdParties" => null,
        "Items" => $detalle,
        "Totals" => [
            "TotalTaxes" => [
                "TotalTax" => [
                    [
                        "Description" => "IVA",
                        "Amount" => number_format($total_impuestos, 5, '.', '')
                    ]
                ]
            ],
            "GrandTotal" => [
                "InvoiceTotal" => number_format($gran_total, 4, '.', '')
            ]
        ],
        "AdditionalDocumentInfo" => [
    "AdditionalInfo" => [
        [
            "Code" => $sale['codigo_secuencial'] ?? "CODIGO-SECUENCIAL-0001",
            "Type" => "ADENDA",
            "AditionalData" => [
                "Data" => [
                    [
                        "Info" => [
                            [
                                "Name" => "OBSERVACIONES",
                                "Data" => null,
                                "Value" => $sale['note'] ?? "-"
                            ],
                            [
                                "Name" => "CANTIDAD_LETRAS",
                                "Data" => null,
                                "Value" => $cantidad_letras
                            ]
                        ]
                    ]
                ]
            ],
            "AditionalInfo" => [
                [
                    "Name" => "VALIDAR_REFERENCIA_INTERNA",
                    "Data" => null,
                    "Value" => "NO_VALIDAR"
                ]
            ]
        ]
    ]
]

    ];

    array_walk_recursive($json, function (&$item) {
        if (is_string($item)) {
            $item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
        }
    });

    return $json;
}

   private function saveInvoice($sale, $cliente, $res, $tipo, $biller, $current_user_id)
{
    $branch_id   = $sale['warehouse_id'] ?? null;
    $branch_name = null;

    if ($branch_id) {
        $branch = $this->db->get_where('sma_warehouses', ['id' => $branch_id])->row_array();
        $branch_name = $branch['name'] ?? null;
    }
    // ==================================================
    // CALCULAR TOTALES DESDE RESPUESTA CERTIFICADA
    // ==================================================

    $total = isset($res['totalAmount']) ? (float)$res['totalAmount'] : 0;

    // IVA 12% incluido en el total
    $iva = $total > 0 ? ($total - ($total / 1.12)) : 0;
    $iva = number_format($iva, 5, '.', '');

    $subtotal = $total > 0 ? number_format(($total / 1.12), 5, '.', '') : 0;
    
$uuid = $res['authNumber'];

$qr_url = 'https://fel.sat.gob.gt/verificador-web/publico/vistas/verificacionDte.jsf?numeroAutorizacion=' . $uuid;

    $data = [

        // Venta
        'ticket_id'   => $sale['reference_no'],
        'branch_id'   => $branch_id,
        'branch_name' => $branch_name,

        // Cliente
        'client_nit'         => $cliente['vat_no'],
        'receptor_nombre'    => $cliente['name'],
        'receptor_direccion' => $cliente['address'],
        'receptor_municipio' => $cliente['municipio'],
        'receptor_departamento' => $cliente['departamento'],
        'receptor_pais'      => $cliente['pais'],

        // FEL (AQUÍ ESTÁ LA CLAVE)
        'uuid'        => $res['authNumber'], // ← ESTE ES EL UUID REAL
        'issued_at'   => !empty($res['issuedTimeStamp']) 
                    ? date('Y-m-d H:i:s', strtotime($res['issuedTimeStamp'])) 
                    : null,
        'tipo_dte'    => $tipo,

        // Archivos
        'xml_base64'  => $res['responseData1'] ?? null,
        'html_base64' => $res['responseData2'] ?? null,
        'pdf_base64'  => $res['responseData3'] ?? null,

        // Totales
        // Totales reales certificados
'grand_total'    => $total,
'total_tax'      => $iva,
'total_discount' => $sale['total_discount'] ?? 0,


        // Serie y número visibles
        'serie'  => $res['batch'] ?? null,
        'numero' => $res['serial'] ?? null,

        // Empresa
        'company_id' => $biller['id'] ?? null,

        // Usuario del sistema que facturó
        'created_by_user_id' => $current_user_id,

        'created_at' => date('Y-m-d H:i:s'),
    ];
log_message('error', 'TOTAL FINAL: ' . $total);
log_message('error', 'IVA FINAL: ' . $iva);
log_message('error', 'TICKET FINAL: ' . $sale['reference_no']);

    if ($this->db->insert('sma_fel_invoices', $data)) {
        log_message('info', 'Factura guardada correctamente: ' . $sale['reference_no']);
        return ['success' => true];
    } else {
        log_message('error', 'Error al guardar factura: ' . $sale['reference_no']);
        return ['success' => false];
    }
}
/*
 * ==================================================
 * OBTENER FACTURAS FEL GUARDADAS
 * SOLO PARA LISTADO EN VISTA
 * ==================================================
 */
public function getFacturas()
{
    return $this->db
        ->order_by('created_at', 'DESC')
        ->get('sma_fel_invoices')
        ->result();
}

private function logJson($json) {
    log_message('error', 'JSON FEL (DEBUG): ' . json_encode($json, JSON_PRETTY_PRINT));
}
// ======================================================
// ANULAR FACTURA FEL
// ======================================================
public function anularFacturaFEL($id, $motivo = 'ANULACION DESDE SISTEMA')
{
    log_message('error', 'anularFacturaFEL: Iniciando anulación de factura con ID ' . $id);

    // 🔎 Obtener factura
    $invoice = $this->db
        ->where('id', $id)
        ->get('sma_fel_invoices')
        ->row();

    if (!$invoice) {
        log_message('error', 'anularFacturaFEL: Factura no encontrada');
        throw new Exception('Factura no encontrada');
    }

    log_message('error', 'anularFacturaFEL: Factura encontrada: ' . json_encode($invoice));

    if ($invoice->anulada == 1) {
        log_message('error', 'anularFacturaFEL: La factura ya está anulada');
        throw new Exception('La factura ya está anulada');
    }

    // 🔌 CONEXION CERTIFICADOR
    $this->load->admin_model('Certificadores_model', 'cert');

    $conexion = $this->db
        ->where('activo', 1)
        ->get('sma_clientes_certificador_conexion')
        ->row();

    if (!$conexion) {
        log_message('error', 'anularFacturaFEL: No hay certificador activo');
        throw new Exception('No hay certificador activo');
    }

    log_message('error', 'anularFacturaFEL: Conexión certificador: ' . json_encode($conexion));

    $username = $conexion->usuario;
    $taxid    = $conexion->nit;

    $certificador = $this->cert->get_certificador($conexion->certificador_id);

    $tokenFEL = $this->cert->get_token_valido($certificador, $conexion);

    if (!$tokenFEL) {
        log_message('error', 'anularFacturaFEL: No se pudo obtener token FEL');
        throw new Exception('No se pudo obtener token FEL');
    }

    log_message('error', 'anularFacturaFEL: Token FEL obtenido');

    // 🧾 ARMAR JSON
    $json = $this->buildJsonCancelDigifact($invoice, $conexion, $motivo);

    log_message('error', 'anularFacturaFEL: JSON para anulación: ' . json_encode($json));

    // 🌐 ENVIAR
    try {
        $result = $this->sendCancelDigifact($json, $tokenFEL, $taxid, $username);
        log_message('error', 'anularFacturaFEL: Resultado de sendCancelDigifact: ' . json_encode($result));
    } catch (Exception $e) {
        log_message('error', 'anularFacturaFEL: Error al enviar a Digifact: ' . $e->getMessage());
        throw $e; // Re-lanza la excepción para que se capture en la función anular()
    }

    // Llamar a la función marcarAnulada
    $this->marcarAnulada($id, $result['response'], $motivo);

    // Devolver el resultado
    return $result;
}
// ======================================================
// ENVIO ANULACION DIGIFACT
// ======================================================
private function sendCancelDigifact($json, $token, $taxid, $username)
{
    $this->logJson($json);

    log_message('error', '======= ENVIO ANULACION FEL =======');

    // Imprimir el token en el log
    log_message('error', 'TOKEN FEL: ' . $token);

    $url = 'https://felgtaws.digifact.com.gt/gt.com.apinuc/api/CancelFelGT'
        . '?TAXID=' . $taxid
        . '&USERNAME=' . $username
        . '&FORMAT=JSON';

    log_message('error', 'URL CANCEL FEL: ' . $url);

    $ch = curl_init($url);

    $body = json_encode($json, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    $headers = [
        "Authorization: " . $token,
        "Content-Type: application/json; charset=utf-8",
        "Accept: application/json",
        "Content-Length: " . strlen($body)
    ];

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_CONNECTTIMEOUT => 30,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => $body
    ]);

    $result = curl_exec($ch);

    if ($result === false) {
        throw new Exception(curl_error($ch));
    }

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    log_message('error', 'HTTP CODE CANCEL FEL: ' . $http_code);
    log_message('error', 'RESPUESTA ANULACION FEL: ' . $result);

    curl_close($ch);

    $response_completa = json_decode($result, true);

    // Ajuste para guardar el acuse como necesitas
    $acuse_formateado = [
        [
            "file_name" => "",
            "file_content" => isset($response_completa['AcuseReciboSAT']) ? $response_completa['AcuseReciboSAT'] : '',
            "url" => "",
            "url_content" => ""
        ]
    ];

    // Devolvemos AMBAS cosas: la respuesta completa y la formateada
    return [
        'response' => $acuse_formateado, // Para guardar en acuse_anulacion
        'response_completa' => $response_completa, // Por si necesitas datos adicionales
        'json_sent' => $json
    ];
}
// ======================================================
// JSON ANULACION DIGIFACT
// ======================================================
private function buildJsonCancelDigifact($invoice, $conexion, $motivo)
{
    // 🔌 Obtener conexión certificador activa (para NIT emisor)
    // $conexion = $this->db  <-- ESTO NO DEBE ESTAR AQUI
    //     ->where('activo', 1)
    //     ->get('sma_clientes_certificador_conexion')
    //     ->row();

    // if (!$conexion) {
    //     throw new Exception('No hay conexión certificador activa');
    // }

    $json = [
        "Taxid" => $conexion->nit, // NIT del emisor
        "Autorizacion" => $invoice->uuid,
        "IdReceptor" => $invoice->client_nit == 'CF' ? 'CF' : $invoice->client_nit, // NIT o CF
        "FechaEmisionDocumentoAnular" => date('Y-m-d\TH:i:s', strtotime($invoice->issued_at)) . '-06:00', // Fecha de emisión
        "MotivoAnulacion" => $motivo, // Motivo de anulación
        "Username" => $conexion->usuario // Usuario
    ];

    return $json;
}
// ===============================================
// MARCAR FACTURA COMO ANULADA
// ===============================================
public function marcarAnulada($id, $respuestaDigifact = null, $motivo = null)
{
    $usuario = $this->session->userdata('user_id');

    $data = [
        'anulada'         => 'SI',
        'fecha_anulacion' => date('Y-m-d H:i:s'),
        'acuse_anulacion' => $respuestaDigifact
            ? json_encode($respuestaDigifact)
            : null,
        'anulada_por'     => $usuario,
        'motivo_anulacion' => $motivo // Guardar el motivo de la anulación
    ];

    $this->db->where('id', $id);

    return $this->db->update('sma_fel_invoices', $data);
}
public function sendDigifactNotaCredito($json, $token, $taxid, $username)
{
    // Guardar log del JSON
    $this->logJson($json);

    log_message('error', '======= DATOS ENVIO NOTA DE CREDITO FEL =======');
    log_message('error', 'TOKEN FEL: ' . $token);
    log_message('error', 'TAXID FEL: ' . $taxid);
    log_message('error', 'USERNAME FEL: ' . $username);

    $url = 'https://nucgt.digifact.com/gt.com.apinuc/api/v2/transform/nuc_json' // URL para notas de crédito
        . '?TAXID=' . $taxid
        . '&USERNAME=' . $username
        . '&FORMAT=XML';

    log_message('error', 'URL FINAL FEL (NOTA CREDITO): ' . $url);

    $ch = curl_init($url);

    $body = json_encode($json, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    if ($body === false) {
        log_message('error', 'ERROR JSON_ENCODE (NOTA CREDITO): ' . json_last_error_msg());
        return ['error' => 'JSON encode failed'];
    }

    $body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');

    log_message('error', 'BODY ENVIADO FEL (NOTA CREDITO): ' . $body);

    // 🔥 DEFINIMOS HEADERS FUERA DEL ARRAY
    $headers = [
        "Authorization: " . $token,
        "Content-Type: application/json; charset=utf-8",
        "Accept: application/json",
        "Content-Length: " . strlen($body)
    ];

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_CONNECTTIMEOUT => 30,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => $body
    ]);

    log_message('error', 'JSON FEL ENVIADO (FORMATEADO - NOTA CREDITO): ' . json_encode($json, JSON_PRETTY_PRINT));

    $result = curl_exec($ch);

    $sent_headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
    log_message('error', 'HEADERS REALES ENVIADOS POR CURL (NOTA CREDITO): ' . $sent_headers);

   if ($result === false) {
        throw new Exception(curl_error($ch));
        log_message('error', 'CURL ERROR FEL (NOTA CREDITO): ' . $errno . ' - ' . $error);
    }

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    log_message('error', 'HTTP CODE FEL (NOTA CREDITO): ' . $http_code);

    curl_close($ch);

    log_message('error', 'FEL RESPONSE (NOTA CREDITO): ' . $result);

    // 🔹 DEVOLVEMOS EL JSON FORMATEADO EN LA RESPUESTA TAMBIÉN
    return [
        'response' => json_decode($result, true),
        'json_sent' => $json // JSON original que se envió
    ];
}
public function buildJsonDigifactNotaCredito($sale, $items, $cliente, $biller, $factura_original, $motivo)
{

    $detalle = [];
    $total_impuestos = 0;
    $gran_total = 0;

    foreach ($items as $indice => $i) {

        $precio = floatval($i['unit_price']);
        $cantidad = floatval($i['quantity']);
        $descuento = floatval($i['discount'] ?? 0);

        $linea_bruta = $precio * $cantidad;
        $linea_total = $linea_bruta - $descuento;

        $base = round($linea_total / 1.12, 6);
        $iva  = round($base * 0.12, 6);

        $detalle[] = [
            "Number" => strval($indice + 1),
            "Codes" => null,
            "Type" => "Bien",
            "Description" => $i['product_name'],
            "Qty" => number_format($cantidad,4,'.',''),
            "UnitOfMeasure" => "UND",
            "Price" => number_format($precio,6,'.',''),
            "Discounts" => $descuento > 0 ? [
                [
                    "Discount" => number_format($descuento,6,'.','')
                ]
            ] : null,
            "Taxes" => [
                "Tax" => [
                    [
                        "Code" => "1",
                        "Description" => "IVA",
                        "TaxableAmount" => number_format($base,6,'.',''),
                        "Amount" => number_format($iva,6,'.','')
                    ]
                ]
            ],
            "Totals" => [
                "TotalItem" => number_format($linea_total,6,'.','')
            ]
        ];

        $total_impuestos += $iva;
        $gran_total += $linea_total;
    }

    // FECHA EXACTA DE CERTIFICACION DEL DOCUMENTO ORIGINAL
    $fecha_origen = date('Y-m-d\TH:i:s', strtotime($factura_original['fecha_certificacion']));

    $json = [

        "Version" => "1.00",
        "CountryCode" => "GT",

        "Header" => [
            "DocType" => "NCRE",
            "IssuedDateTime" => date('c'),
            "Currency" => "GTQ"
        ],

        "Seller" => [
            "TaxID" => $biller['vat_no'],
            "TaxIDAdditionalInfo" => [
                [
                    "Name" => "AfiliacionIVA",
                    "Data" => null,
                    "Value" => "GEN"
                ]
            ],
            "Name" => $biller['name'],
            
"AdditionlInfo" => [
                [
  "Name" => "TipoFrase",
  "Data" => "1",
  "Value" => "1"
],
[
  "Name" => "Escenario",
  "Data" => "1",
  "Value" => "1"
],
],
            "BranchInfo" => [
                "Code" => "1",
                "Name" => $biller['name'],
                "AddressInfo" => [
                    "Address" => $biller['address'],
                    "City" => $biller['postal_code'],
                    "District" => $biller['city'],
                    "State" => $biller['state'],
                    "Country" => "GT"
                ]
            ]
        ],

        "Buyer" => [
            "TaxID" => $cliente['nit'],
            "Name" => $cliente['nombre'],
            "AddressInfo" => [
                "Address" => $cliente['direccion'],
                "City" => "01001",
                "District" => $cliente['municipio'],
                "State" => $cliente['departamento'],
                "Country" => "GT"
            ]
        ],

        "Items" => $detalle,

        "Totals" => [
            "TotalTaxes" => [
                "TotalTax" => [
                    [
                        "Description" => "IVA",
                        "Amount" => number_format($total_impuestos,6,'.','')
                    ]
                ]
            ],
            "GrandTotal" => [
                "InvoiceTotal" => number_format($gran_total,6,'.','')
            ]
        ],

        "AdditionalDocumentInfo" => [
            "AdditionalInfo" => [

                [
                    "Code" => "NCRE",
                    "Type" => "COMPLEMENTO",
                    "AditionalInfo" => [

                        [
                            "Name" => "NumeroAutorizacionDocumentoOrigen",
                            "Data" => null,
                            "Value" => $factura_original['uuid']
                        ],
                        [
                            "Name" => "FechaEmisionDocumentoOrigen",
                            "Data" => null,
                            "Value" => date('Y-m-d', strtotime($factura_original['issued_at']))
                        ],
                        [
                            "Name" => "MotivoAjuste",
                            "Data" => null,
                            "Value" => $motivo
                        ],
                        [
                            "Name" => "NumeroDocumentoOrigen",
                            "Data" => null,
                            "Value" => $factura_original['numero']
                        ],
                        [
                            "Name" => "SerieDocumentoOrigen",
                            "Data" => null,
                            "Value" => $factura_original['serie']
                        ]

                    ]
                ],

                [
                    "Code" => "FRONT-" . strtoupper(uniqid()),
                    "Type" => "ADENDA",
                    "AditionalData" => [
                        "Data" => [
                            [
                                "Name" => "INFORMACION_ADICIONAL",
                                "Info" => [
                                    [
                                        "Name" => "OBSERVACIONES",
                                        "Data" => null,
                                        "Value" => "-"
                                    ],
                                    [
                                        "Name" => "CANTIDAD_LETRAS",
                                        "Data" => null,
                                        "Value" => "-"
                                    ]
                                ]
                            ]
                        ]
                    ],
                    "AditionalInfo" => [
                        [
                            "Name" => "VALIDAR_REFERENCIA_INTERNA",
                            "Data" => null,
                            "Value" => "NO_VALIDAR"
                        ]
                    ]
                ]

            ]
        ]

    ];

    return $json;
}
public function saveNotaCredito($nota_credito, $factura, $res, $biller, $current_user_id, $items)
{

    $branch_id   = $factura['branch_id'] ?? null;
    $branch_name = $factura['branch_name'] ?? null;

    $total           = $nota_credito['total'] ?? 0;
    $total_tax       = $nota_credito['total_tax'] ?? 0;
    $subtotal        = $nota_credito['subtotal'] ?? 0;
    $total_discount  = $nota_credito['total_discount'] ?? 0;

    $uuid = $res['authNumber'] ?? null;

    $qr_url = $uuid
        ? 'https://fel.sat.gob.gt/verificador-web/publico/vistas/verificacionDte.jsf?numeroAutorizacion=' . $uuid
        : null;

    $data = [

        'reference_no'   => $factura['ticket_id'] ?? null,
        'invoice_id'     => $factura['id'] ?? null,
        'date'           => date('Y-m-d H:i:s'),

        'total'          => $total,
        'total_tax'      => $total_tax,
        'total_discount' => $total_discount,
        'subTotal'       => $subtotal,
        'totalAmount'    => $total,

        'uuid'           => $uuid,
        'serie'          => $res['batch'] ?? null,
        'numero'         => $res['serial'] ?? null,
        'autorizacion'   => $uuid,

        'fecha_certificacion' =>
            !empty($res['issuedTimeStamp'])
                ? date('Y-m-d H:i:s', strtotime($res['issuedTimeStamp']))
                : null,

        'xml_base64'     => $res['responseData1'] ?? null,
        'html_base64'    => $res['responseData2'] ?? null,
        'pdf_base64'     => $res['responseData3'] ?? null,

        'qr_url'         => $qr_url,

        'created_by'     => $current_user_id,
        'created_at'     => date('Y-m-d H:i:s'),

        'digifact_response' => json_encode($res),

        'note'           => $nota_credito['note'] ?? null,

        'branch_id'      => $branch_id,
        'branch_name'    => $branch_name,

        'code'           => $res['code'] ?? null,
        'message'        => $res['message'] ?? null,
        'description'    => $res['description'] ?? null,
        'url'            => $res['url'] ?? null,

        'infoDetails'    => isset($res['infoDetails']) ? json_encode($res['infoDetails']) : null,

        'suggestedFileName' => $res['suggestedFileName'] ?? null,

        'receiverTaxID'  => $res['receiverTaxID'] ?? null,
        'receiverName'   => $res['receiverName'] ?? null,
    ];

    $this->db->insert('sma_fel_notas_credito', $data);

    $nota_credito_id = $this->db->insert_id();


    /**
     * ============================
     * GUARDAR ITEMS
     * ============================
     */

    if (!empty($items)) {

        foreach ($items as $item) {

            $item_data = [

                'nota_credito_id' => $nota_credito_id,
                'product_id'      => $item['product_id'] ?? null,
                'product_code'    => $item['product_code'] ?? null,
                'product_name'    => $item['product_name'] ?? null,
                'quantity'        => $item['quantity'] ?? 0,
                'unit_price'      => $item['unit_price'] ?? 0,
                'taxable_amount'  => $item['taxable_amount'] ?? 0,
                'tax_amount'      => $item['tax_amount'] ?? 0,
                'total'           => $item['total'] ?? 0,
                'discount'        => $item['discount'] ?? 0,

            ];

            $this->db->insert('sma_fel_nota_credito_items', $item_data);

        }

    }


    /**
     * ============================
     * MARCAR FACTURA COMO NCRE
     * ============================
     */

    $this->db
        ->where('id', $factura['id'])
        ->update('sma_fel_invoices', ['ncre' => 'SI']);


    log_message('error', 'NOTA CREDITO GUARDADA ID: ' . $nota_credito_id);
    log_message('error', 'UUID NCRE: ' . $uuid);


    return [

        'success' => true,
        'nota_credito_id' => $nota_credito_id

    ];

}
}