<?php

require_once('public/lib/print/num_letras.php');
class PseModel extends Model
{

    public function __construct()
    {
        parent::__construct();
    }



    public function getDataComprobante($id_venta)
    {

        $comprobante = $this->getDataDocumento($id_venta);

        if ($comprobante === null) {

            return;
        }

        $empresa = $this->getDataEmpresa();
        $cliente = $this->getDataCliente($comprobante['id_cliente']);
        $dataSecret = $this->getSecretData();


        $data = [

            "token_cliente" => "FACTURALAYA_BZ1GPEX6RJ21EKIRAM56",
            "ruc_proveedor" => "10470949444",
            "secret_data" => $dataSecret,
            "emisor" => [
                "ruc" => $empresa['ruc'],
                "tipo_doc" => "6",
                "email" => "aquino.alex@gmail.com",
                "nom_comercial" => $empresa['nombre_comercial'],
                "razon_social" => $empresa['razon_social'],
                "codigo_ubigeo" => $empresa['ubigeo'],
                "direccion" => $empresa['direccion_fiscal'],
                "modalidad_envio_sunat" => "inmediato",
                "direccion_departamento" => $empresa['departamento'],
                "direccion_provincia" => $empresa['provincia'],
                "direccion_distrito" => $empresa['distrito'],
                "direccion_codigopais" => "PE",
            ],
            "cliente_tipodocumento" => $cliente['tipo_cliente'] == 2 ? 6 : 1,
            "cliente_numerodocumento" => $cliente['tipo_cliente'] == 2 ? $cliente['ruc'] : $cliente['dni'],
            "cliente_nombre" => $cliente['tipo_cliente'] == 2 ? $cliente['razon_social'] : $cliente['nombres'],
            "cliente_direccion" => $cliente['direccion'],
            "cliente_pais" => "PE",
            "cliente_ciudad" => "Huanuco",
            "cliente_codigoubigeo" => "",
            "cliente_departamento" => "",
            "cliente_provincia" => "",
            "cliente_distrito" => "",
            "detalle" => $comprobante['detalle'],
            "tipo_operacion" => "0101",
            "total_gravadas" => 0.00,
            "total_inafecta" => 0.00,
            "total_exoneradas" => (float) $comprobante['total'],
            "total_gratuitas" => 0.00,
            "total_exportacion" => 0.00,
            "total_isc" => 0.00,
            "total_icbper" => 0.00,
            "total_otr_imp" => 0.00,
            "total_descuento" => 0.00,
            "impuesto_icbper" => 0.00,
            "porcentaje_igv" => 18,
            "total_igv" => 0.00,
            "sub_total" => (float) $comprobante['total'],
            "total" => (float) $comprobante['total'],
            "total_letras" => numtoletras($comprobante['total']),
            "docs_referencia" => [],
            "nro_otr_comprobante" => "",
            "transporte_nro_placa" => "",
            "cod_moneda" => "PEN",
            "cod_sucursal_sunat" => "0000",
            "fecha_comprobante" => substr($comprobante['fecha_venta'], 0, 10),
            "fecha_vto_comprobante" => substr($comprobante['fecha_venta'], 0, 10),
            "forma_de_pago" => "contado",
            "monto_deuda_total" => 0.00,
            "detalle_cuotas" => [],
            "cod_tipo_documento" => $this->codigoDocumentoPorNumero((int) $comprobante['id_tipo_doc']),
            "serie_comprobante" => $comprobante['serie_doc'],
            //"serie_comprobante" => "F001",
            "numero_comprobante" => (int) $comprobante['nro_doc'],
            "modalidad_envio_sunat" => "inmediato",
        ];

        return $data;

    }

    public function getDataComprobanteBaja($id_venta)
    {

        if ($id_venta <= 0) {
            throw new \InvalidArgumentException("id_venta inválido.");
        }

        $empresa = $this->getDataEmpresa();
        $dataSecret = $this->getSecretData();


        $data = [
            "token_cliente" => "FACTURALAYA_BZ1GPEX6RJ21EKIRAM56",
            "ruc_proveedor" => "10470949444",
            "secret_data" => $dataSecret,
            "emisor" => [
                "ruc" => $empresa['ruc'],
                "tipo_doc" => "6",
                "email" => "aquino.alex@gmail.com",
                "nom_comercial" => $empresa['nombre_comercial'],
                "razon_social" => $empresa['razon_social'],
                "codigo_ubigeo" => $empresa['ubigeo'],
                "direccion" => $empresa['direccion_fiscal'],
                "modalidad_envio_sunat" => "inmediato",
                "direccion_departamento" => $empresa['departamento'],
                "direccion_provincia" => $empresa['provincia'],
                "direccion_distrito" => $empresa['distrito'],
                "direccion_codigopais" => "PE",
            ],
            "cabecera" => $this->getDataCabeceraBaja($id_venta),
            "detalle" => $this->getDataDocBaja($id_venta)
        ];

        return $data;

    }

    public function getDataComprobanteResumen($id_venta)
    {

        if ($id_venta <= 0) {
            throw new \InvalidArgumentException("id_venta inválido.");
        }

        $empresa = $this->getDataEmpresa();
        $documento = $this->getDataDocResumen($id_venta);
        $dataSecret = $this->getSecretData();


        $data = [

            "token_cliente" => "FACTURALAYA_BZ1GPEX6RJ21EKIRAM56",
            "ruc_proveedor" => "10470949444",
            "secret_data" => $dataSecret,
            "emisor" => [
                "ruc" => $empresa['ruc'],
                "tipo_doc" => "6",
                "email" => "aquino.alex@gmail.com",
                "nom_comercial" => $empresa['nombre_comercial'],
                "razon_social" => $empresa['razon_social'],
                "codigo_ubigeo" => $empresa['ubigeo'],
                "direccion" => $empresa['direccion_fiscal'],
                "modalidad_envio_sunat" => "inmediato",
                "direccion_departamento" => $empresa['departamento'],
                "direccion_provincia" => $empresa['provincia'],
                "direccion_distrito" => $empresa['distrito'],
                "direccion_codigopais" => "PE",
            ],

        ] + $documento;

        return $data;

    }

    private function getSecretData(): array
    {
        // 1) Traer empresa/contribuyente
        $sql = "SELECT * FROM tm_empresa LIMIT 1";
        $stmt = $this->db->query($sql);
        $e = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$e) {
            throw new \RuntimeException("Los datos de la empresa no fueron encontrados.");
        }

        $directoriobeta = 'api_fact/UBL21/archivos_xml_sunat/certificados/beta/' . $e['ruc'];
        $directorioproduccion = 'api_fact/UBL21/archivos_xml_sunat/certificados/produccion/' . $e['ruc'];

        $isProd = $e['modo'] == 1;
        $isPse = $e['certpse'] == 1;

        $secret = [
            'tipo_proceso' => $isProd ? 'produccion' : 'prueba',
            'tipo_certificado' => $isPse ? 'pse_facturalaya' : 'propio', // <-- siempre definido
            'file_certificado' => '',
            'pass_certificado' => '',
            'usuariosol' => '',
            'clavesol' => '',

            'ruta_certificado' => '',
            'ruta_dir_xml' => '',
            'ruc_pse' => '',

            'auth_api_sunat_ruc' => $e['ruc'] ?? '',
            'auth_api_sunat_usol' => '',
            'auth_api_sunat_csol' => '',
            'auth_api_sunat_id' => $e['client_id'] ?? '',
            'auth_api_sunat_secret' => $e['client_secret'] ?? '',
        ];

        $rutaXml = $isProd ? $directorioproduccion : $directoriobeta;
        if (!is_dir($rutaXml)) {
            @mkdir($rutaXml, 0777, true);
        }
        $secret['ruta_dir_xml'] = $rutaXml;

        // 5) Ramas exactas de tu lógica
        if ($isProd) {
            if (!$isPse) {
                // PRODUCCIÓN con certificado PROPIO
                $rutaPfx = $directorioproduccion . '/' . $e['ruc'] . '.pfx';
                if (!is_file($rutaPfx) || !is_readable($rutaPfx)) {
                    return [
                        'respuesta' => 'error',
                        'titulo' => 'Error RUTA Certificado',
                        'mensaje' => 'No se encuentra la ruta del certificado de producción',
                    ];
                }

                $secret['ruta_certificado'] = $rutaPfx;
                $secret['file_certificado'] = base64_encode(file_get_contents($rutaPfx));
                $secret['pass_certificado'] = (string) ($e['clavecertificado'] ?? '');
                $secret['usuariosol'] = (string) ($e['usuariosol'] ?? '');
                $secret['clavesol'] = (string) ($e['clavesol'] ?? '');

                // ya está tipo_certificado = 'propio'
            } else {
                // PRODUCCIÓN con PSE (no envías PFX ni SOL)
                $secret['ruta_certificado'] = '';
                $secret['file_certificado'] = '';
                $secret['pass_certificado'] = '';
                $secret['usuariosol'] = '';
                $secret['clavesol'] = '';
                $secret['ruc_pse'] = $e['ruc_pse'] ?? ''; // si lo manejas
                // tipo_certificado = 'pse_facturalaya'
            }
        } else {
            // PRUEBA (usa PFX de prueba y credenciales MODDATOS)
            $rutaPfx = $directoriobeta . '/firmabeta.pfx';
            if (!is_file($rutaPfx)) {
                return [
                    'respuesta' => 'error',
                    'titulo' => 'Error RUTA Certificado',
                    'mensaje' => 'No se encuentra la ruta del certificado',
                ];
            }

            $secret['ruta_certificado'] = $rutaPfx;
            $secret['file_certificado'] = base64_encode(file_get_contents($rutaPfx));
            $secret['pass_certificado'] = '123456';
            $secret['tipo_proceso'] = 'prueba';
            $secret['usuariosol'] = 'MODDATOS';
            $secret['clavesol'] = 'moddatos';
            $secret['tipo_certificado'] = 'propio'; // así lo tenías
        }

        return $secret;
    }

    private function codigoDocumentoPorNumero(int $n): ?string
    {
        static $map = [
        1 => '03',
        2 => '01',
        3 => '77'
        ];
        return $map[$n] ?? null; // null si no existe
    }

    public function getDataCliente(int $id_cliente): ?array
    {
        try {
            $sql = "SELECT * FROM tm_cliente WHERE id_cliente = :id LIMIT 1";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':id', $id_cliente, \PDO::PARAM_INT);
            $stmt->execute();

            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $row ?: null;
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function getDataEmpresa(): ?array
    {
        try {
            // Si solo tienes 1 registro de empresa, usa LIMIT 1
            $sql = "SELECT * FROM tm_empresa LIMIT 1";
            $stmt = $this->db->query($sql);
            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $row ?: null;
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function getDataDocumento(int $id_venta): ?array
    {
        try {


            $sql = "SELECT * FROM tm_venta WHERE id_venta = :id LIMIT 1";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':id', $id_venta, \PDO::PARAM_INT);
            $stmt->execute();

            $venta = $stmt->fetch(\PDO::FETCH_ASSOC);

            if (!$venta) {
                return null;
            }


            $igvPercent = 0;
            $igvRate = $igvPercent / 100.0;


            $sqlDet = "
                SELECT
                    d.id_prod,
                    pp.cod_prod,
                    SUM(d.cantidad)                               AS cantidad_total,
                    SUM(d.cantidad * d.precio)                    AS total,
                    'NIU'                                           AS unidad_medida,
                    COALESCE(MAX(pp.cod_prod), '')                  AS codigo_det,
                    COALESCE(MAX(pp.presentacion), '')            AS presentacion
                FROM tm_detalle_venta d
                INNER JOIN tm_producto_pres pp ON pp.id_pres = d.id_prod
                WHERE d.id_venta = :id_ref
                GROUP BY d.id_prod
                ORDER BY MIN(d.id_prod) ASC
            ";

            $stDet = $this->db->prepare($sqlDet);
            $stDet->execute(['id_ref' => (int) $venta['id_venta']]);
            $rows = $stDet->fetchAll(\PDO::FETCH_ASSOC) ?: [];

            $detalle = [];
            $item = 1;

            foreach ($rows as $r) {
                $cant = (float) $r['cantidad_total'];
                $importeCon = (float) $r['total'];                 // total con IGV
                $precioCon = $cant > 0 ? round($importeCon / $cant, 2) : 0.0;                 // unitario con IGV
                $precioSin = round($precioCon / (1 + $igvRate), 2);                              // unitario sin IGV
                $importeSin = round($importeCon / (1 + $igvRate), 2);                             // total sin IGV
                $igvDet = round($importeCon - $importeSin, 2);

                $desc = trim(($r['presentacion'] ?? ''));

                $detalle[] = [
                    "ITEM_DET" => (int) $item++,
                    "UNIDAD_MEDIDA_DET" => $r['unidad_medida'] ?: 'NIU',
                    "PRECIO_TIPO_CODIGO" => "01",
                    "COD_TIPO_OPERACION_DET" => "20",
                    "CANTIDAD_DET" => $cant,
                    "PRECIO_DET" => $precioCon,      // unitario CON IGV
                    "IGV_DET" => $igvDet,         // IGV total del ítem
                    "ICBPER_DET" => 0,
                    "ISC_DET" => 0,
                    "PRECIO_SIN_IGV_DET" => $precioSin,      // unitario SIN IGV
                    "IMPORTE_DET" => round($importeCon, 2), // total CON IGV
                    "CODIGO_DET" => $r['codigo_det'],
                    "DESCRIPCION_DET" => $desc,
                    "DESCUENTO_ITEM" => "no",
                    "PORCENTAJE_DESCUENTO" => 0,
                    "MONTO_DESCUENTO" => 0,
                    "CODIGO_DESCUENTO" => "00",
                ];
            }


            $venta['detalle'] = $detalle;

            return $venta;

        } catch (\Throwable $th) {
            throw $th;
        }
    }

    private function getDataDocBaja(int $id_venta): array
    {
        $sql = "SELECT * FROM tm_venta WHERE id_venta = :id LIMIT 1";
        $stmt = $this->db->prepare($sql);
        $stmt->bindValue(':id', $id_venta, \PDO::PARAM_INT);
        $stmt->execute();

        $venta = $stmt->fetch(\PDO::FETCH_ASSOC);
        if (!$venta) {
            throw new \InvalidArgumentException("Venta no encontrada: {$id_venta}");
        }

        $tipo = $this->codigoDocumentoPorNumero((int) ($venta['id_tipo_doc'] ?? 0));
        if (!in_array($tipo, ['01', '03', '07', '08'], true)) {
            throw new \InvalidArgumentException("Tipo de comprobante inválido para baja: {$tipo}");
        }

        $serie = strtoupper(trim((string) ($venta['serie_doc'] ?? '')));
        $numero = (int) ($venta['nro_doc'] ?? 0);

        if ($serie === '' || $numero <= 0) {
            throw new \InvalidArgumentException("Serie y número del comprobante son obligatorios.");
        }

        // Opcional: validar formato común de serie (ej. F001, B001, etc.)
        // if (!preg_match('/^[A-Z0-9]{1}[A-Z0-9]{3,}$/', $serie)) { ... }

        $detalleItem = [
            "ITEM_DET" => 1,
            "TIPO_COMPROBANTE" => $tipo,
            "SERIE" => $serie,
            "NUMERO" => $numero,
            "MOTIVO" => "Error en el RUC", // ajusta tu motivo si corresponde
        ];


        return [$detalleItem];
    }

    private function getDataDocResumen(int $id_venta): array
    {

        $sql = $sql = "
            SELECT
            v.*,
            c.dni        AS dni_cliente,
            c.estado     AS estado_cliente
            FROM tm_venta v
            INNER JOIN tm_cliente c
            ON c.id_cliente = v.id_cliente
            AND c.estado = 'a'
            WHERE v.id_venta = :id
        LIMIT 1";

        $stmt = $this->db->prepare($sql);
        $stmt->bindValue(':id', $id_venta, \PDO::PARAM_INT);
        $stmt->execute();

        $venta = $stmt->fetch(\PDO::FETCH_ASSOC);
        if (!$venta) {
            throw new \InvalidArgumentException("Venta no encontrada: {$id_venta}");
        }

        $tipo = $this->codigoDocumentoPorNumero((int) ($venta['id_tipo_doc'] ?? 0)); // tu helper existente
        if (!in_array($tipo, ['03', '07', '08'], true)) {
            throw new \InvalidArgumentException("Solo Boletas (03) y Notas de Boleta (07/08) van en RC. Tipo: {$tipo}");
        }

        $serie = strtoupper(trim((string) ($venta['serie_doc'] ?? ''))); // ej. B001
        $numero = (int) ($venta['nro_doc'] ?? 0);                        // ej. 4
        if ($serie === '' || $numero <= 0) {
            throw new \InvalidArgumentException("Serie y número del comprobante son obligatorios.");
        }
        $nroComprobante = "{$serie}-{$numero}";

        $tipoDocCli = "1"; // por defecto DNI

        $fechaEmision = $venta['fecha_venta'] ?? $venta['fecha_venta'] ?? date('Y-m-d'); // ajusta nombre de columna
        $fechaReferencia = (new \DateTime($fechaEmision))->format('Y-m-d');
        $fechaDocumento = date('Y-m-d'); // hoy
        $serieRC = (new \DateTime($fechaDocumento))->format('Ymd'); // p.ej. 20240702
        $secuencia = $this->obtenerSiguienteSecuenciaRC();

        $moneda = strtoupper((string) ($venta['moneda'] ?? 'PEN'));
        $gravada = (float) ($venta['op_gravada'] ?? $venta['total_gravadas'] ?? 0);
        $exonerado = (float) ($venta['op_exonerada'] ?? $venta['total_exoneradas'] ?? 0);
        $inafecto = (float) ($venta['op_inafecta'] ?? $venta['total_inafecta'] ?? 0);
        $exporta = (float) ($venta['op_exportacion'] ?? $venta['total_exportacion'] ?? 0);
        $gratuitas = (float) ($venta['op_gratuitas'] ?? $venta['total_gratuitas'] ?? 0);
        $igv = (float) ($venta['igv'] ?? $venta['total_igv'] ?? 0);
        $isc = 0;
        $otros = 0;
        $icbper = (float) ($venta['icbper'] ?? 0);
        $numDocCli = trim((string) ($venta['dni_cliente'] ?? '00000000'));

        $total = (float) ($venta['total'] ?? $venta['importe_total'] ?? 0);
        if ($total <= 0) {
            $total = $gravada + $exonerado + $inafecto + $exporta + $igv + $isc + $otros; // ICBPER normalmente ya va sumado; ajusta según tu modelo
        }

        $status = 3;

        // 8) Armar estructura RC
        $detalleItem = [
            "ITEM_DET" => 1,
            "TIPO_COMPROBANTE" => $tipo,
            "NRO_COMPROBANTE" => $nroComprobante,
            "NRO_DOCUMENTO" => $numDocCli,
            "TIPO_DOCUMENTO" => $tipoDocCli, // "1"=DNI, "6"=RUC, "0"=SIN DOC
            "NRO_COMPROBANTE_REF" => "",          // para notas: pon aquí el doc base si aplica
            "TIPO_COMPROBANTE_REF" => "",          // "03" si refieres boleta
            "STATUS" => $status,
            "COD_MONEDA" => $moneda,
            "TOTAL" => round($total, 2),
            "GRAVADA" => round($gravada, 2),
            "EXONERADO" => round($exonerado, 2),
            "INAFECTO" => round($inafecto, 2),
            "EXPORTACION" => round($exporta, 2),
            "ICBPER" => round($icbper, 2),
            "GRATUITAS" => round($gratuitas, 2),
            "IGV" => round($igv, 2),
            "MONTO_CARGO_X_ASIG" => "0",
            "CARGO_X_ASIGNACION" => "0",
            "ISC" => round($isc, 2),
            "OTROS" => round($otros, 2),
        ];

        return [
            "codigo" => "RC",
            "serie" => $serieRC,        // p.ej. "20240702"
            "secuencia" => $secuencia,
            "fecha_referencia" => $fechaReferencia,
            "fecha_documento" => $fechaDocumento,
            "detalle" => [$detalleItem],
        ];
    }

    /**
     * Mapea tu valor de tipo de doc de cliente a los códigos SUNAT (1=DNI, 6=RUC, 0=Sin Doc).
     * Si el CPE es boleta y no hay doc, devuelve "0".
     */
    private function mapTipoDocCliente($rawTipo, string $tipoCpe): string
    {
        $t = strtoupper(trim((string) $rawTipo));
        if ($t === '' && $tipoCpe === '03') {
            return '0';
        }
        // Acepta variantes comunes
        $map = [
            'DNI' => '1',
            '1' => '1',
            'RUC' => '6',
            '6' => '6',
            'CE' => '4',
            '4' => '4',
            'PAS' => '7',
            '7' => '7',
            '0' => '0',
        ];
        return $map[$t] ?? '0';
    }

    /**
     * Devuelve la siguiente secuencia del RC para una fecha dada.
     * Implementa aquí tu lógica real (tabla de resumenes, etc.). Por ahora: 1.
     */
    private function obtenerSiguienteSecuenciaRC(): int
    {
        $tz = new \DateTimeZone('America/Lima');
        $ahora = new \DateTimeImmutable('now', $tz);
        // Secuencia: mismo cálculo que mostraste (desde medianoche)
        $inicioDia = new \DateTimeImmutable($ahora->format('Y-m-d') . ' 00:00:00', $tz);
        $intervalo = $inicioDia->diff($ahora);
        // concatena horas y minutos (como string) y suma los segundos
        $secuencia = (int) ($intervalo->h . $intervalo->i) + (int) $intervalo->s;

        // Asegura que sea al menos 1
        if ($secuencia < 1) {
            $secuencia = 1;
        }
        return $secuencia;
    }

    private function getDataCabeceraBaja(int $id_venta): array
    {
        $sql = "SELECT * FROM tm_venta WHERE id_venta = :id LIMIT 1";
        $stmt = $this->db->prepare($sql);
        $stmt->bindValue(':id', $id_venta, \PDO::PARAM_INT);
        $stmt->execute();

        $venta = $stmt->fetch(\PDO::FETCH_ASSOC);
        if (!$venta) {
            throw new \InvalidArgumentException("Venta no encontrada: {$id_venta}");
        }

        // Tipo de comprobante (factura, boleta, NC, ND)
        $tipo = $this->codigoDocumentoPorNumero((int) ($venta['id_tipo_doc'] ?? 0));
        if (!in_array($tipo, ['01', '03', '07', '08'], true)) {
            throw new \InvalidArgumentException("Tipo de comprobante inválido para baja: {$tipo}");
        }

        $serie = strtoupper(trim((string) ($venta['serie_doc'] ?? '')));
        $numero = (int) ($venta['nro_doc'] ?? 0);

        if ($serie === '' || $numero <= 0) {
            throw new \InvalidArgumentException("Serie y número del comprobante son obligatorios.");
        }

        // === Armamos la cabecera de la comunicación de baja (RA) ===
        $tz = new \DateTimeZone('America/Lima');
        $ahora = new \DateTimeImmutable('now', $tz);
        $fechaHoy = $ahora->format('Y-m-d');   // ej. 2025-08-25
        $serieRA = $ahora->format('Ymd');     // ej. 20250825

        // Secuencia: mismo cálculo que mostraste (desde medianoche)
        $inicioDia = new \DateTimeImmutable($ahora->format('Y-m-d') . ' 00:00:00', $tz);
        $intervalo = $inicioDia->diff($ahora);
        // concatena horas y minutos (como string) y suma los segundos
        $secuencia = (int) ($intervalo->h . $intervalo->i) + (int) $intervalo->s;

        // Asegura que sea al menos 1
        if ($secuencia < 1) {
            $secuencia = 1;
        }

        return [
            "codigo" => $tipo == "03" ? "RC" : "RA",
            "serie" => $serieRA,
            "secuencia" => $secuencia,
            "fecha_referencia" => (new \DateTimeImmutable($venta['fecha_venta'] ?? $fechaHoy))->format('Y-m-d'),
            "fecha_baja" => $fechaHoy,
        ];
    }

    public function setDataDocumento(
        int $id_venta,
        int $enviado_sunat,
        ?string $code_respuesta_sunat,
        ?string $descripcion_sunat_cdr,
        ?string $name_file_sunat,
        ?string $hash_cdr,
        ?string $hash_cpe,
        ?string $estado
    ): bool {
        try {
            $sql = "UPDATE tm_venta
                   SET enviado_sunat         = :enviado_sunat,
                       code_respuesta_sunat  = :code_respuesta_sunat,
                       descripcion_sunat_cdr = :descripcion_sunat_cdr,
                       name_file_sunat       = :name_file_sunat,
                       hash_cdr              = :hash_cdr,
                       hash_cpe              = :hash_cpe,
                       estado                = :estado
                 WHERE id_venta = :id_venta";

            $stmt = $this->db->prepare($sql);
            $ok = $stmt->execute([
                ':enviado_sunat' => $enviado_sunat,
                ':code_respuesta_sunat' => $code_respuesta_sunat,
                ':descripcion_sunat_cdr' => $descripcion_sunat_cdr,
                ':name_file_sunat' => $name_file_sunat,
                ':hash_cdr' => $hash_cdr,
                ':hash_cpe' => $hash_cpe,
                ':id_venta' => $id_venta,
                ':estado' => $estado
            ]);

            // rowCount puede ser 0 si los valores son iguales; igual consideramos éxito si ejecutó.
            return $ok && $stmt->rowCount() >= 0;
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function validarBaja(int $id_venta): bool
    {
        try {
            $sql = "SELECT fecha_venta FROM tm_venta WHERE id_venta = :id_venta LIMIT 1";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':id_venta', $id_venta, \PDO::PARAM_INT);
            $stmt->execute();

            $fechaVenta = $stmt->fetchColumn();
            if (!$fechaVenta) {
                // No existe la venta
                return false;
            }

            // Normalizamos fechas en zona horaria Lima
            $tz = new \DateTimeZone('America/Lima');
            $fechaVenta = new \DateTimeImmutable($fechaVenta, $tz);
            $hoy = new \DateTimeImmutable('today', $tz);

            $dias = $fechaVenta->diff($hoy)->days;

            // Si pasaron más de 7 días -> no se puede dar de baja
            if ($dias > 6) {
                return false;
            }

            return true;

        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function reponerStock(int $id_venta) {
    try {
        $this->db->beginTransaction();

        // 1. Obtener los detalles de la venta con información adicional del producto
        $sqlDetalles = "SELECT dv.id_prod, dv.cantidad, pp.crt_stock, pp.receta 
                       FROM tm_detalle_venta dv
                       JOIN tm_producto_pres pp ON dv.id_prod = pp.id_pres 
                       WHERE dv.id_venta = :id_venta";
        $stmtDetalles = $this->db->prepare($sqlDetalles);
        $stmtDetalles->bindValue(':id_venta', $id_venta, \PDO::PARAM_INT);
        $stmtDetalles->execute();
        $detalles = $stmtDetalles->fetchAll(\PDO::FETCH_ASSOC);

        if (!$detalles) {
            $this->db->commit();
            return;
        }

        foreach ($detalles as $detalle) {
            // Si tiene control de stock y receta
            if ($detalle['crt_stock'] == 1 && $detalle['receta'] == 1) {
                // Obtener ingredientes y cantidades
                $sqlIngr = "SELECT id_ins, cant FROM tm_producto_ingr WHERE id_pres = :id_pres";
                $stmtIngr = $this->db->prepare($sqlIngr);
                $stmtIngr->bindValue(':id_pres', $detalle['id_prod'], \PDO::PARAM_INT);
                $stmtIngr->execute();
                $ingredientes = $stmtIngr->fetchAll(\PDO::FETCH_ASSOC);

                // Actualizar stock de insumos
                $sqlUpdateIns = "UPDATE tm_insumo SET stock = stock + :cantidad 
                               WHERE id_ins = :id_ins";
                $stmtUpdateIns = $this->db->prepare($sqlUpdateIns);

                foreach ($ingredientes as $ingrediente) {
                    $cantidadTotal = $ingrediente['cant'] * $detalle['cantidad'];
                    $stmtUpdateIns->bindValue(':cantidad', $cantidadTotal, \PDO::PARAM_INT);
                    $stmtUpdateIns->bindValue(':id_ins', $ingrediente['id_ins'], \PDO::PARAM_INT);
                    $stmtUpdateIns->execute();
                }
            }
            // Si solo tiene control de stock
            elseif ($detalle['crt_stock'] == 1 && $detalle['receta'] == 0) {
                $sqlUpdateStock = "UPDATE tm_producto_pres 
                                 SET stock = stock + :cantidad 
                                 WHERE id_pres = :id_prod";
                $stmtUpdateStock = $this->db->prepare($sqlUpdateStock);
                $stmtUpdateStock->bindValue(':cantidad', $detalle['cantidad'], \PDO::PARAM_INT);
                $stmtUpdateStock->bindValue(':id_prod', $detalle['id_prod'], \PDO::PARAM_INT);
                $stmtUpdateStock->execute();
            }
        }

        $this->db->commit();
    } catch (\Throwable $th) {
        $this->db->rollBack();
        throw $th;
    }
}





}