<?php
session_start();
require_once 'includes/db.php';
require_once 'includes/funciones_registro.php';

// Verificar que la solicitud sea POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('HTTP/1.1 400 Bad Request');
    echo json_encode([
        'success' => false,
        'message' => 'Método no permitido'
    ]);
    exit;
}

$response = ['success' => false, 'message' => ''];

/*
 * Registra una actividad de venta finalizada
 * 
 * @param int $usuario_id ID del usuario que realiza la venta
 * @param array $info_venta Información de la venta realizada
 * @return bool True si se registró correctamente, False en caso contrario
 */
function registrar_actividad_venta($usuario_id, $info_venta) {
    try {
        // Obtener símbolo de moneda
        $simbolo_moneda = obtener_moneda();
        
        // Construir el mensaje con el nuevo formato solicitado
        $detalleVenta = "Venta #{$info_venta['num_venta']}";
        
        // Agregar información del cliente si está disponible con un separador |
        if (!empty($info_venta['cliente_nombre'])) {
            // Incluir el documento si está disponible
            $documento = !empty($info_venta['cliente_documento']) ? " - " . $info_venta['cliente_documento'] : "";
            $detalleVenta .= " | Cliente: {$info_venta['cliente_nombre']}{$documento}";
        }
        
        // Calcular montos por tipo de venta
        $total_contado = isset($info_venta['total_contado']) ? $info_venta['total_contado'] : 0;
        $total_credito_inicial = isset($info_venta['monto_primera_cuota']) ? $info_venta['monto_primera_cuota'] : 0;
        $entrega_inicial = isset($info_venta['entrega_inicial']) ? $info_venta['entrega_inicial'] : 0;
        
        // Calcular el total de efectivo recibido incluyendo la entrega inicial
        $total_efectivo = $total_contado + $total_credito_inicial + $entrega_inicial;
        $detalleVenta .= " | EFECTIVO RECIBIDO: {$simbolo_moneda}" . number_format($total_efectivo, 2);
        
        // Agregar los conceptos de pago solo si hay alguno
        $conceptos = [];
        
        if ($total_contado > 0) {
            $conceptos[] = "AL CONTADO: " . $simbolo_moneda . number_format($total_contado, 2);
        }
        
        if ($entrega_inicial > 0) {
            $conceptos[] = "ENTREGA DE VALORES: " . $simbolo_moneda . number_format($entrega_inicial, 2);
        }
        
        if ($total_credito_inicial > 0) {
            $conceptos[] = "PRIMERA CUOTA CRÉDITO: " . $simbolo_moneda . number_format($total_credito_inicial, 2);
        }
        
        // Combinar los conceptos con comas y agregar al detalle solo si hay conceptos
        if (!empty($conceptos)) {
            $detalleVenta .= " | CONCEPTOS: " . implode(", ", $conceptos);
        } else {
            $detalleVenta .= " | SIN CONCEPTOS DE PAGO REGISTRADOS";
        }
        
        // Llamar a la función general de registro
        return registrarActividadUsuario($usuario_id, 'venta_finalizada', $detalleVenta);
    } catch (Exception $e) {
        error_log("Error al registrar actividad de venta: " . $e->getMessage());
        return false;
    }
}

/**
 * Registra un error en el sistema
 * 
 * @param int $usuario_id ID del usuario donde ocurre el error
 * @param string $mensaje Mensaje de error
 * @return bool True si se registró correctamente, False en caso contrario
 */
function registrar_actividad_error($usuario_id, $mensaje) {
    try {
        return registrarActividadUsuario($usuario_id, 'error_sistema', $mensaje);
    } catch (Exception $e) {
        error_log("Error al registrar actividad de error: " . $e->getMessage());
        return false;
    }
}

/**
 * Obtiene el símbolo de moneda de la configuración
 * 
 * @return string Símbolo de moneda configurado o $ por defecto
 */
function obtener_moneda() {
    try {
        $db = new Database();
        $pdo = $db->getPDO();
        $stmt = $pdo->query("SELECT moneda FROM configuracion LIMIT 1");
        $config = $stmt->fetch(PDO::FETCH_ASSOC);
        return $config && isset($config['moneda']) ? $config['moneda'] : '$';
    } catch (Exception $e) {
        error_log("Error al obtener moneda de configuración: " . $e->getMessage());
        return '$';
    }
}

/**
 * Ajusta la fecha hasta encontrar un día hábil
 * @param DateTime $fecha
 * @param PDO $pdo
 * @return DateTime
 */
function ajustar_fecha_habil($fecha, $pdo) {
    $fecha_ajustada = clone $fecha;
    
    do {
        $es_valida = true;
        
        // Verificar si es domingo
        if ($fecha_ajustada->format('N') == 7) {
            $fecha_ajustada->modify('+1 day');
            $es_valida = false;
            continue;
        }
        
        // Verificar si es feriado - usando formato de fecha específico
        $stmt = $pdo->prepare("
            SELECT COUNT(*) as es_feriado 
            FROM feriados 
            WHERE DATE(fecha) = DATE(:fecha)
        ");
        
        $fecha_formateada = $fecha_ajustada->format('Y-m-d');
        $stmt->execute([':fecha' => $fecha_formateada]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($result['es_feriado'] > 0) {

            $fecha_ajustada->modify('+1 day');
            $es_valida = false;
        }
        
    } while (!$es_valida);
    
    return $fecha_ajustada;
}

/**
 * Ajusta la fecha de aviso teniendo en cuenta días hábiles
 * @param DateTime $fecha_vencimiento Fecha de vencimiento original
 * @param int $dias Días a sumar o restar
 * @param PDO $pdo Conexión a la base de datos
 * @return DateTime
 */

function ajustar_fecha_aviso($fecha_vencimiento, $dias, $pdo) {
    $fecha_aviso = clone $fecha_vencimiento;
    
    // Si los días son negativos (para primer aviso)
    if ($dias < 0) {
        $fecha_aviso->modify("$dias days");
        // Ajustar hacia atrás hasta encontrar día hábil
        while (true) {
            $es_domingo = $fecha_aviso->format('N') == 7;
            
            // Verificar si es feriado
            $stmt = $pdo->prepare("SELECT COUNT(*) as es_feriado FROM feriados WHERE DATE(fecha) = DATE(:fecha)");
            $stmt->execute([':fecha' => $fecha_aviso->format('Y-m-d')]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($es_domingo || $result['es_feriado'] > 0) {
                $fecha_aviso->modify('-1 day');
            } else {
                break;
            }
        }
    }
    // Si los días son positivos (para tercer aviso)
    else if ($dias > 0) {
        $fecha_aviso->modify("+$dias days");
        // Ajustar hacia adelante hasta encontrar día hábil
        while (true) {
            $es_domingo = $fecha_aviso->format('N') == 7;
            
            // Verificar si es feriado
            $stmt = $pdo->prepare("SELECT COUNT(*) as es_feriado FROM feriados WHERE DATE(fecha) = DATE(:fecha)");
            $stmt->execute([':fecha' => $fecha_aviso->format('Y-m-d')]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($es_domingo || $result['es_feriado'] > 0) {
                $fecha_aviso->modify('+1 day');
            } else {
                break;
            }
        }
    }
    
    return $fecha_aviso;
}

try {
    $db = new Database();
    $pdo = $db->getPDO();
    
    // Definir $fechaActual al inicio del bloque try
    $fechaActual = new DateTime();
    
    // Validar y obtener datos del POST primero
    if (!isset($_POST['venta_id'])) {
        throw new Exception('ID de venta no proporcionado');
    }
    $venta_id = $_POST['venta_id'];

    if (!isset($_POST['cliente_id'])) {
        throw new Exception('ID de cliente no proporcionado');
    }
    $cliente_id = intval($_POST['cliente_id']);
    
    // Siempre unificar cuotas por defecto
    $unificar_cuotas = true;
    
    // Procesar las cuotas unificadas
    if ($unificar_cuotas) {
        // Calcular el total de crédito
        $stmt = $pdo->prepare("
            SELECT SUM(subtotal) as total_credito,
                   MAX(cantidad_cuotas) as max_cuotas,
                   MAX(CASE WHEN grupo_id LIKE 'venta_sem_%' THEN 1 ELSE 0 END) as es_semanal,
                   venta_id
            FROM venta_items 
            WHERE cliente_id = :cliente_id 
            AND estado = 'EN_CURSO'
            AND tipo_venta = 'credito'
            GROUP BY venta_id
        ");
        
        $stmt->execute([':cliente_id' => $cliente_id]);
        $creditoInfo = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($creditoInfo && $creditoInfo['total_credito'] > 0) {
            // Usar el venta_id de los items si existe
            $venta_id = $creditoInfo['venta_id'];
            $total_credito = floatval($creditoInfo['total_credito']);
            $cantidad_cuotas = intval($creditoInfo['max_cuotas']);
            $es_semanal = boolval($creditoInfo['es_semanal']);
            
            // Calcular monto por cuota unificada
            $monto_cuota = $total_credito / $cantidad_cuotas;
            
            // Actualizar todos los items a crédito para usar el mismo grupo_id
            $grupo_unificado = $es_semanal ? 'venta_sem_unificada_' . time() : 'venta_unificada_' . time();
            
            $stmt = $pdo->prepare("
                UPDATE venta_items 
                SET grupo_id = :grupo_id
                WHERE cliente_id = :cliente_id 
                AND estado = 'EN_CURSO'
                AND tipo_venta = 'credito'
            ");
            
            $stmt->execute([
                ':grupo_id' => $grupo_unificado,
                ':cliente_id' => $cliente_id
            ]);
        }
    }

    // Verificar configuración de venta con stock 0
    $stmtConfigStock = $pdo->query("SELECT vender_stock_0 FROM configuracion LIMIT 1");
    $configStock = $stmtConfigStock->fetch(PDO::FETCH_ASSOC);
    $permitir_venta_sin_stock = isset($configStock['vender_stock_0']) ? (int)$configStock['vender_stock_0'] : 0;

    // Validar stock antes de proceder con la venta si no está permitido vender sin stock
    if (!$permitir_venta_sin_stock) {
        $stmt = $pdo->prepare("
            SELECT vi.producto_id, vi.cantidad, p.stock, p.titulo
            FROM venta_items vi
            JOIN productos p ON p.id = vi.producto_id
            WHERE vi.cliente_id = :cliente_id 
            AND vi.estado = 'EN_CURSO'
            AND p.stock <= 0
        ");
        $stmt->execute(['cliente_id' => $cliente_id]);
        $productos_sin_stock = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (!empty($productos_sin_stock)) {
            $productos_error = array_map(function($item) {
                return $item['titulo'];
            }, $productos_sin_stock);
            
            throw new Exception("No se puede completar la venta. Los siguientes productos no tienen stock disponible: " . implode(", ", $productos_error));
        }
    }

    // Obtener configuración de días de aviso
    $stmtConfig = $pdo->query("
        SELECT dias_primer_aviso, dias_tercer_aviso 
        FROM configuracion 
        LIMIT 1
    ");
    $configDias = $stmtConfig->fetch(PDO::FETCH_ASSOC);
    $diasPrimerAviso = isset($configDias['dias_primer_aviso']) ? (int)$configDias['dias_primer_aviso'] : 0;
    $diasTercerAviso = isset($configDias['dias_tercer_aviso']) ? (int)$configDias['dias_tercer_aviso'] : 0;
    
    // Verificar que existe usuario en sesión
    if (!isset($_SESSION['usuario_id'])) {
        throw new Exception('Usuario no autenticado');
    }
    $usuario_id = $_SESSION['usuario_id'];
    
    // Iniciar transacción
    $pdo->beginTransaction();
    
    // Desactivar temporalmente la verificación de claves foráneas
    $pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
    
    // Recibir y validar datos
    $items_cuotas = isset($_POST['items_cuotas']) ? $_POST['items_cuotas'] : [];
    if (is_string($items_cuotas)) {
        $items_cuotas = json_decode($items_cuotas, true);
    }
    $cliente_id = isset($_POST['cliente_id']) ? $_POST['cliente_id'] : 0;
    
    // Recibir datos de cuotas_items que incluyen los días de crédito
    $cuotas_items = isset($_POST['cuotas_items']) ? $_POST['cuotas_items'] : [];
    if (is_string($cuotas_items)) {
        $cuotas_items = json_decode($cuotas_items, true);
    }

    // Procesar entrega inicial si existe
    $entrega_inicial = isset($_POST['entrega_inicial']) ? 
        floatval(str_replace(',', '.', str_replace('.', '', $_POST['entrega_inicial']))) : 0;

    // Si hay entrega inicial, registrarla como pago
    if ($entrega_inicial > 0) {
        $stmt = $pdo->prepare("
            INSERT INTO pagos (
                venta_id, 
                monto, 
                tipo, 
                numero_cuota,
                fecha_pago, 
                fecha_vencimiento, 
                estado,
                usuario_id,
                producto_id
            ) VALUES (
                :venta_id,
                :monto,
                'ENTREGA_INICIAL',
                0,
                NOW(),
                NOW(),
                'PENDIENTE',
                :usuario_id,
                0
            )
        ");
        
        $stmt->execute([
            ':venta_id' => $venta_id,
            ':monto' => $entrega_inicial,
            ':usuario_id' => $usuario_id
        ]);
    }

    // Obtener el total de crédito y ajustarlo con la entrega inicial
    $total_credito = isset($_POST['total_credito']) ? 
        floatval(str_replace(',', '.', str_replace('.', '', $_POST['total_credito']))) : 0;

    // Si hay entrega inicial, ajustar el total de crédito
    if ($entrega_inicial > 0) {
        $total_credito = max(0, $total_credito - $entrega_inicial);
    }

    // Inicializar variables para el registro de actividad
    $total_venta = 0;
    $total_items = 0;
    $total_productos = 0;
    $productos_nombres = [];
    $productos_detallados = [];
    $tipo_venta_general = 'contado';
    $hay_primera_cuota = false;
    $monto_primera_cuota = 0;
    $total_efectivo = 0;

    // Obtener información del cliente para el registro de actividad
    $cliente_nombre = "Cliente #" . $cliente_id;
    $cliente_documento = "";
    if ($cliente_id > 0) {
        try {
            // Actualizar la consulta para obtener información completa del cliente
            $stmt = $pdo->prepare("
                SELECT nombre, apellidos, tipo_documento, numero_documento
                FROM clientes 
                WHERE id_cliente = :id LIMIT 1
            ");
            $stmt->execute([':id' => $cliente_id]);
            $cliente_data = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($cliente_data) {
                // Formatear el nombre completo del cliente
                $nombre_completo = trim($cliente_data['nombre'] . ' ' . ($cliente_data['apellidos'] ?? ''));
                
                // Formatear el documento con tipo y número
                $tipo_doc = $cliente_data['tipo_documento'] ?? '';
                $num_doc = $cliente_data['numero_documento'] ?? '';
                $documento_completo = trim($tipo_doc . ' ' . $num_doc);
                
                // Asignar los valores obtenidos
                $cliente_nombre = $nombre_completo;
                $cliente_documento = $documento_completo;
                
            } else {
                $cliente_nombre = "Cliente ID: " . $cliente_id;
                $cliente_documento = "";
            }
        } catch (Exception $e) {
            $cliente_nombre = "Cliente ID: " . $cliente_id;
            $cliente_documento = "";
        }
    }
    
    // Actualizar montos de primera cuota para cada item
    if (!empty($items_cuotas)) {
        
        // Crear un array único por ID de item
        $items_procesados = [];
        foreach ($items_cuotas as $item) {
            if (isset($item['id']) && !isset($items_procesados[$item['id']])) {
                $items_procesados[$item['id']] = $item;
            }
        }

        $stmt = $pdo->prepare("
            UPDATE venta_items 
            SET monto_primera_cuota = :monto,
                entrega_inicial = :entrega_inicial,
                total_credito_ajustado = :total_credito_ajustado
            WHERE id = :id
        ");
        
        // Procesar cada item único para actualizar monto de primera cuota
        foreach ($items_procesados as $item) {
            if (isset($item['monto_primera_cuota'])) {
                $monto = floatval($item['monto_primera_cuota']);
                
                $stmt->execute([
                    ':monto' => $monto,
                    ':id' => $item['id'],
                    ':entrega_inicial' => $entrega_inicial,
                    ':total_credito_ajustado' => $total_credito
                ]);
            }
            
            // Recopilar información básica para registro de actividad
            if (isset($item['tipo_venta']) && strtolower($item['tipo_venta']) === 'credito') {
                $tipo_venta_general = 'credito';
            }
            
            if (isset($item['primera_cuota']) && (int)$item['primera_cuota'] === 1) {
                $hay_primera_cuota = true;
                if (isset($item['monto_primera_cuota'])) {
                    $monto_primera_cuota += floatval($item['monto_primera_cuota']);
                }
            }
            
            // Calcular totales y recopilar información de productos
            if (isset($item['subtotal'])) {
                $total_venta += floatval($item['subtotal']);
                $total_items++;
                
                $cantidad = isset($item['cantidad']) ? (int)$item['cantidad'] : 1;
                $total_productos += $cantidad;
                
                $nombre_producto = !empty($item['titulo']) ? $item['titulo'] : 
                                  (!empty($item['codigo']) ? "Producto " . $item['codigo'] : 
                                  "Producto #" . $item['producto_id']);
                                  
                $productos_nombres[] = $nombre_producto . " (x" . $cantidad . ")";
                
                // Guardar todos los detalles del producto para el registro detallado
                $productos_detallados[] = $item;
                
                // Sumar al total de efectivo si es contado o si tiene primera cuota
                if (isset($item['tipo_venta']) && strtolower($item['tipo_venta']) === 'contado') {
                    $total_efectivo += floatval($item['subtotal']);
                } else if (isset($item['primera_cuota']) && (int)$item['primera_cuota'] === 1 && isset($item['monto_primera_cuota'])) {
                    $total_efectivo += floatval($item['monto_primera_cuota']);
                }
            }
        }

        // Actualizar otros items del mismo grupo que no estén en items_cuotas
        if (!empty($items_procesados)) {
            $firstItem = reset($items_procesados);
            if (isset($firstItem['grupo_id']) && !empty($firstItem['grupo_id'])) {
                $stmt = $pdo->prepare("
                    UPDATE venta_items 
                    SET monto_primera_cuota = subtotal / 2
                    WHERE grupo_id = :grupo_id 
                    AND id NOT IN (" . implode(',', array_keys($items_procesados)) . ")
                    AND tipo_venta = 'credito'
                ");
                
                $stmt->execute([
                    ':grupo_id' => $firstItem['grupo_id']
                ]);
            }
        }
    }

    // Generar un número de venta
    try {
        // Intentar obtener el número de la venta directamente de venta_items usando venta_id
        $stmtVenta = $pdo->prepare("
            SELECT venta_id
            FROM venta_items
            WHERE cliente_id = :cliente_id 
            AND estado = 'EN_CURSO'
            GROUP BY venta_id
            LIMIT 1
        ");
        
        $stmtVenta->execute([':cliente_id' => $cliente_id]);
        $venta_dato = $stmtVenta->fetch(PDO::FETCH_ASSOC);
        
        if ($venta_dato && !empty($venta_dato['venta_id'])) {
            $num_venta = $venta_dato['venta_id'];
        } else {
            // Si no hay items procesados o no tienen venta_id, generar uno nuevo
            $num_venta = 'V-' . date('Ymd') . '-' . substr(time(), -4);
        }
    } catch (Exception $e) {
        error_log("Error al obtener número de venta: " . $e->getMessage());
        $num_venta = 'V-' . date('Ymd') . '-' . substr(time(), -4);
    }

    // SECCIÓN CRÍTICA: Procesar las cuotas
    if (isset($_POST['items_cuotas']) || true) { // Siempre ejecutar este bloque
        
        // Preparar la sentencia SQL para cuotas antes de usarla
        $stmtCuotas = $pdo->prepare("
            INSERT INTO cuotas 
            (venta_id, numero_cuota, monto, fecha_vencimiento, fecha_pago, estado, usuario_id, 
             monto_primera_cuota, cliente_id, producto_id, primer_aviso, segundo_aviso, tercer_aviso, observaciones) 
            VALUES 
            (:venta_id, :numero_cuota, :monto, :fecha_vencimiento, :fecha_pago, :estado, :usuario_id, 
             :monto_primera_cuota, :cliente_id, :producto_id, :primer_aviso, :segundo_aviso, :tercer_aviso, :observaciones)
        ");

        // Si las cuotas están unificadas, usar el monto total ajustado y cantidad de cuotas máxima
        if ($unificar_cuotas && isset($total_credito) && isset($cantidad_cuotas)) {
            // El total_credito ya viene ajustado con la entrega inicial
            $montoCuota = $total_credito / $cantidad_cuotas;
            
            // Obtener los IDs de productos vendidos con sus cantidades
            $stmt = $pdo->prepare("
                SELECT DISTINCT producto_id, cantidad 
                FROM venta_items 
                WHERE cliente_id = :cliente_id 
                AND estado = 'EN_CURSO'
                AND tipo_venta = 'credito'
            ");
            $stmt->execute([':cliente_id' => $cliente_id]);
            $productos = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Crear string de productos con sus cantidades separados por coma
            $observaciones_productos = implode(',', array_map(function($producto) {
                return $producto['producto_id'] . '/' . $producto['cantidad'];
            }, $productos));
            
            // Usar la misma fecha de vencimiento para todas las cuotas unificadas
            $fechaVencimiento = clone $fechaActual;
            if ($es_semanal) {
                $intervalo = 7; // días para cuotas semanales
            } else {
                $intervalo = 30; // días para cuotas mensuales
            }
            
            // Si hay entrega inicial, registrarla como primera cuota
            $entrega_inicial = isset($_POST['entrega_inicial']) ? floatval($_POST['entrega_inicial']) : 0;
            $numero_cuota_inicial = 1;

            if ($entrega_inicial > 0) {
                // Registrar la entrega inicial como primera cuota (ya pagada)
                $stmtCuotas->execute([
                    ':venta_id' => $venta_id,
                    ':numero_cuota' => 1,
                    ':monto' => $entrega_inicial,
                    ':fecha_vencimiento' => $fechaActual->format('Y-m-d'),
                    ':fecha_pago' => $fechaActual->format('Y-m-d H:i:s'),
                    ':estado' => 'PAGADO',
                    ':usuario_id' => $usuario_id,
                    ':monto_primera_cuota' => $entrega_inicial,
                    ':cliente_id' => $cliente_id,
                    ':producto_id' => 0,
                    ':primer_aviso' => $fechaActual->format('Y-m-d'),
                    ':segundo_aviso' => $fechaActual->format('Y-m-d'),
                    ':tercer_aviso' => $fechaActual->format('Y-m-d'),
                    ':observaciones' => $observaciones_productos
                ]);
                
                // La entrega inicial ya fue restada del total_credito anteriormente
                $cantidad_cuotas--;
                $montoCuota = $total_credito / $cantidad_cuotas; // Dividir el monto restante entre las cuotas pendientes
                $numero_cuota_inicial = 2;
            }

            // Obtener la fecha seleccionada para la segunda cuota
            $fechaSegundaCuota = isset($_POST['fecha_segunda_cuota']) ? new DateTime($_POST['fecha_segunda_cuota']) : null;

            // Generar las cuotas restantes
            for ($i = $numero_cuota_inicial; $i <= ($entrega_inicial > 0 ? $cantidad_cuotas + 1 : $cantidad_cuotas); $i++) {
                if ($i === 1 || ($i === 2 && $entrega_inicial > 0)) {
                    // Para la primera cuota (sin entrega inicial) o segunda cuota (con entrega inicial)
                    $fechaVencimiento = clone $fechaActual;
                    $fechaVencimiento->modify("+30 days");
                } else {
                    // Para las cuotas posteriores
                    $fechaVencimiento = clone $fechaActual;
                    $diasAdicionales = ($entrega_inicial > 0 ? $i - 1 : $i) * 30;
                    $fechaVencimiento->modify("+{$diasAdicionales} days");
                }
                $fechaVencimiento = ajustar_fecha_habil($fechaVencimiento, $pdo);
                
                // Calcular fechas de aviso
                $fechaPrimerAviso = ajustar_fecha_aviso($fechaVencimiento, -$diasPrimerAviso, $pdo);
                $fechaTercerAviso = ajustar_fecha_aviso($fechaVencimiento, $diasTercerAviso, $pdo);
                
                $stmtCuotas->execute([
                    ':venta_id' => $venta_id,
                    ':numero_cuota' => $i,
                    ':monto' => $montoCuota,
                    ':fecha_vencimiento' => $fechaVencimiento->format('Y-m-d'),
                    ':fecha_pago' => null,
                    ':estado' => 'PENDIENTE',
                    ':usuario_id' => $usuario_id,
                    ':monto_primera_cuota' => 0,  // Ya no necesitamos esto aquí porque la primera cuota se maneja por separado
                    ':cliente_id' => $cliente_id,
                    ':producto_id' => 0, // 0 para cuotas unificadas
                    ':primer_aviso' => $fechaPrimerAviso->format('Y-m-d'),
                    ':segundo_aviso' => $fechaVencimiento->format('Y-m-d'),
                    ':tercer_aviso' => $fechaTercerAviso->format('Y-m-d'),
                    ':observaciones' => $observaciones_productos // Ahora incluye ids y cantidades
                ]);
            }
        } else {
            // Mantener la lógica original para cuotas separadas
            // Preparar las sentencias SQL para cuotas y pagos
            $stmtCuotas = $pdo->prepare("
                INSERT INTO cuotas 
                (venta_id, numero_cuota, monto, fecha_vencimiento, fecha_pago, estado, usuario_id, 
                 monto_primera_cuota, cliente_id, producto_id, primer_aviso, segundo_aviso, tercer_aviso) 
                VALUES 
                (:venta_id, :numero_cuota, :monto, :fecha_vencimiento, :fecha_pago, :estado, :usuario_id, 
                 :monto_primera_cuota, :cliente_id, :producto_id, :primer_aviso, :segundo_aviso, :tercer_aviso)
            ");

            $stmtPagos = $pdo->prepare("
                INSERT INTO pagos 
                (venta_id, monto, tipo, numero_cuota, fecha_pago, fecha_vencimiento, estado, usuario_id, producto_id) 
                VALUES 
                (:venta_id, :monto, :tipo, :numero_cuota, :fecha_pago, :fecha_vencimiento, :estado, :usuario_id, :producto_id)
            ");

            // Obtener TODOS los items de venta a crédito, independientemente del POST
            $stmtItems = $pdo->prepare("
                SELECT * 
                FROM venta_items 
                WHERE cliente_id = :cliente_id 
                AND estado = 'EN_CURSO'
                AND LOWER(tipo_venta) = 'credito'
                AND cantidad_cuotas > 0
            ");
            
            $stmtItems->execute([':cliente_id' => $cliente_id]);
            $itemsVenta = $stmtItems->fetchAll(PDO::FETCH_ASSOC);
            
            $itemsCount = count($itemsVenta);

            
            if ($itemsCount > 0) {
                // Procesamiento de cuotas para cada item de venta a crédito
                foreach ($itemsVenta as $item) {
                    // Extraer y validar datos del item
                    $producto_id = isset($item['producto_id']) ? $item['producto_id'] : 0;
                    if (!$producto_id) {
                        error_log("Item sin producto_id válido: " . print_r($item, true));
                        continue;
                    }
                    
                    $venta_id = isset($item['venta_id']) ? $item['venta_id'] : '';
                    if (empty($venta_id)) {
                        error_log("Item sin venta_id válido: " . print_r($item, true));
                        continue;
                    }
                    
                    $montoTotal = floatval($item['subtotal']);
                    $cantidadCuotas = intval($item['cantidad_cuotas']);
                    $montoPrimeraCuota = floatval($item['monto_primera_cuota']);
                    $primeraCuotaPagada = intval($item['primera_cuota']) === 1;
                    

                    
                    if ($cantidadCuotas <= 0) {

                        continue;
                    }
                    
                    $fechaActual = new DateTime();
                    $montoPendiente = $montoTotal;
                    
                    // Procesar la entrega inicial como primera cuota
                    $entregaInicial = floatval(isset($_POST['entrega_inicial']) ? $_POST['entrega_inicial'] : 0);
                    if ($entregaInicial > 0) {
                        $montoPendiente -= $entregaInicial;
                        
                        // La primera cuota es la entrega inicial, con vencimiento hoy
                        $fechaVencimiento = clone $fechaActual;
                        $fechaPrimerAviso = clone $fechaActual;
                        $fechaTercerAviso = clone $fechaActual;
                        
                        // Insertar la entrega inicial como primera cuota ya pagada
                        try {
                            $stmtCuotas->execute([
                                ':venta_id' => $venta_id,
                                ':numero_cuota' => 1,
                                ':monto' => $entregaInicial,
                                ':fecha_vencimiento' => $fechaVencimiento->format('Y-m-d'),
                                ':fecha_pago' => $fechaActual->format('Y-m-d'),
                                ':estado' => 'PAGADO',
                                ':usuario_id' => $usuario_id,
                                ':monto_primera_cuota' => $entregaInicial,
                                ':cliente_id' => $cliente_id,
                                ':producto_id' => $producto_id,
                                ':primer_aviso' => $fechaPrimerAviso->format('Y-m-d'),
                                ':segundo_aviso' => $fechaVencimiento->format('Y-m-d'),
                                ':tercer_aviso' => $fechaTercerAviso->format('Y-m-d')
                            ]);
                            
                            // Registrar el pago correspondiente
                            $stmtPagos->execute([
                                ':venta_id' => $venta_id,
                                ':monto' => $montoPrimeraCuota,
                                ':tipo' => 'PRIMERA_CUOTA',
                                ':numero_cuota' => 1,
                                ':fecha_pago' => $fechaActual->format('Y-m-d H:i:s'),
                                ':fecha_vencimiento' => $fechaActual->format('Y-m-d'),
                                ':estado' => 'PENDIENTE',
                                ':usuario_id' => $usuario_id,
                                ':producto_id' => $producto_id
                            ]);
                            
                        } catch (Exception $e) {
                            throw $e;
                        }
                        
                        // Ajustar para las cuotas restantes
                        $cuotasRestantes = $cantidadCuotas - 1;
                        $numeroCuotaInicial = 2;
                    } else {
                        $cuotasRestantes = $cantidadCuotas;
                        $numeroCuotaInicial = 1;
                    }
                    
                    // Si quedan cuotas por generar
                    if ($cuotasRestantes > 0 && $montoPendiente > 0) {
                        // Determinar si es un plan semanal
                        $esSemanal = strpos($item['grupo_id'], 'venta_sem_') === 0;
                        
                        // Calcular el monto de cada cuota ANTES del bucle
                        $montoCuota = $montoPendiente / $cuotasRestantes;

                        // Obtener el día de vencimiento de la configuración
                        $stmtConfig = $pdo->query("SELECT dia_vence_pagare FROM configuracion LIMIT 1");
                        $configDia = $stmtConfig->fetch(PDO::FETCH_ASSOC);
                        $diaVencePagare = isset($configDia['dia_vence_pagare']) ? (int)$configDia['dia_vence_pagare'] : 1;

                        // Calcular la primera fecha de vencimiento
                        $fechaPrimeraVencimiento = clone $fechaActual;
                        if ($esSemanal) {
                            // Para pagos semanales, ir a la próxima semana y ajustar al día configurado
                            $fechaPrimeraVencimiento->modify('+7 days');
                            // Ajustar al día de la semana configurado sin validar días hábiles
                            $diaActual = (int)$fechaPrimeraVencimiento->format('N');
                            $diferencia = $diaVencePagare - $diaActual;
                            if ($diferencia <= 0) {
                                $diferencia += 7;
                            }
                            $fechaPrimeraVencimiento->modify("+{$diferencia} days");
                        } else {
                            // Para pagos mensuales, mantener la lógica actual
                            $fechaPrimeraVencimiento->modify('+30 days');
                            $fechaPrimeraVencimiento = ajustar_fecha_habil($fechaPrimeraVencimiento, $pdo);
                        }

                        // Generar cuotas restantes
                        for ($i = 0; $i < $cuotasRestantes; $i++) {
                            $numeroCuota = $numeroCuotaInicial + $i;
                            if ($esSemanal) {
                                // Para cuotas semanales: solo usar segundo y tercer aviso
                                $fechaVencimiento = clone $fechaPrimeraVencimiento;
                                if ($i > 0) {
                                    $fechaVencimiento->modify("+" . ($i * 7) . " days");
                                }

                                // Para cuotas semanales: registrar segundo aviso (mismo día del vencimiento)
                                // y tercer aviso (2 días después)
                                $fechaTercerAviso = clone $fechaVencimiento;
                                $fechaTercerAviso->modify("+2 days");

                                try {
                                    $stmtCuotas->execute([
                                        ':venta_id' => $venta_id,
                                        ':numero_cuota' => $numeroCuota,
                                        ':monto' => $montoCuota,
                                        ':fecha_vencimiento' => $fechaVencimiento->format('Y-m-d'),
                                        ':fecha_pago' => null,
                                        ':estado' => 'PENDIENTE',
                                        ':usuario_id' => $usuario_id,
                                        ':monto_primera_cuota' => 0,
                                        ':cliente_id' => $cliente_id,
                                        ':producto_id' => $producto_id,
                                        ':primer_aviso' => null,  // Primer aviso null para cuotas semanales
                                        ':segundo_aviso' => $fechaVencimiento->format('Y-m-d'),  // Segundo aviso el mismo día
                                        ':tercer_aviso' => $fechaTercerAviso->format('Y-m-d')   // Tercer aviso 2 días después
                                    ]);
                                } catch (Exception $e) {
                                    error_log("Error al generar cuota #{$numeroCuota}: " . $e->getMessage());
                                    throw $e;
                                }
                            } else {
                                // Para cuotas mensuales mantener la lógica existente
                                $fechaVencimiento = clone $fechaPrimeraVencimiento;
                                if ($i > 0) {
                                    $fechaVencimiento->modify("+" . ($i * 30) . " days");
                                    $fechaVencimiento = ajustar_fecha_habil($fechaVencimiento, $pdo);
                                }

                                // Calcular fechas de aviso para cuotas mensuales
                                $fechaPrimerAviso = ajustar_fecha_aviso($fechaVencimiento, -$diasPrimerAviso, $pdo);
                                $fechaTercerAviso = ajustar_fecha_aviso($fechaVencimiento, $diasTercerAviso, $pdo);

                                try {
                                    $stmtCuotas->execute([
                                        ':venta_id' => $venta_id,
                                        ':numero_cuota' => $numeroCuota,
                                        ':monto' => $montoCuota,
                                        ':fecha_vencimiento' => $fechaVencimiento->format('Y-m-d'),
                                        ':fecha_pago' => null,
                                        ':estado' => 'PENDIENTE',
                                        ':usuario_id' => $usuario_id,
                                        ':monto_primera_cuota' => 0,
                                        ':cliente_id' => $cliente_id,
                                        ':producto_id' => $producto_id,
                                        ':primer_aviso' => $fechaPrimerAviso->format('Y-m-d'),
                                        ':segundo_aviso' => $fechaVencimiento->format('Y-m-d'),
                                        ':tercer_aviso' => $fechaTercerAviso->format('Y-m-d')
                                    ]);
                                } catch (Exception $e) {
                                    error_log("Error al generar cuota #{$numeroCuota}: " . $e->getMessage());
                                    throw $e;
                                }
                            }
                        }
                    }
                }
            } else {

            }
        }
    }

    // Reactivar la verificación de claves foráneas
    $pdo->exec('SET FOREIGN_KEY_CHECKS = 1');

    // Descontar el stock de los productos vendidos
    try {
        // Obtener todos los items de la venta actual
        $stmt = $pdo->prepare("
            SELECT vi.venta_id, vi.producto_id, vi.cantidad, p.stock, p.titulo
            FROM venta_items vi
            JOIN productos p ON p.id = vi.producto_id
            WHERE vi.cliente_id = :cliente_id 
            AND vi.estado = 'EN_CURSO'
        ");
        $stmt->execute(['cliente_id' => $cliente_id]);
        $items = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Actualizar el stock de cada producto
        $stmtUpdate = $pdo->prepare("
            UPDATE productos 
            SET stock = stock - :cantidad
            WHERE id = :producto_id
            AND (stock >= :cantidad OR :permitir_venta_sin_stock = 1)
        ");

        foreach ($items as $item) {
            if (!$permitir_venta_sin_stock && $item['stock'] < $item['cantidad']) {
                throw new Exception("Stock insuficiente para el producto: {$item['titulo']}");
            }

            $stmtUpdate->execute([
                'cantidad' => $item['cantidad'],
                'producto_id' => $item['producto_id'],
                'permitir_venta_sin_stock' => $permitir_venta_sin_stock
            ]);

            if ($stmtUpdate->rowCount() === 0) {
                throw new Exception("No se pudo actualizar el stock del producto: {$item['titulo']}");
            }
        }
    } catch (Exception $e) {
        error_log("Error al actualizar stock: " . $e->getMessage());
        throw new Exception("Error al actualizar inventario: " . $e->getMessage());
    }

    // Actualizar el estado de todos los items de la venta a COMPLETADO
    $stmt = $pdo->prepare("
        UPDATE venta_items 
        SET estado = 'COMPLETADO'
        WHERE cliente_id = :cliente_id 
        AND estado = 'EN_CURSO'
    ");
    
    $stmt->execute([
        'cliente_id' => $cliente_id
    ]);

    // Actualizar los días de crédito para los items a crédito
    if (!empty($cuotas_items)) {
        foreach ($cuotas_items as $cuota_item) {
            if (isset($cuota_item['item_id']) && isset($cuota_item['dias_credito'])) {
                if ($cuota_item['item_id'] === 'unificado') {
                    // Si es unificado, actualizar todos los items a crédito del cliente
                    $stmt = $pdo->prepare("
                        UPDATE venta_items 
                        SET dias_credito = :dias_credito
                        WHERE cliente_id = :cliente_id 
                        AND estado = 'COMPLETADO'
                        AND tipo_pago = 'credito'
                    ");
                    
                    $stmt->execute([
                        ':dias_credito' => $cuota_item['dias_credito'],
                        ':cliente_id' => $cliente_id
                    ]);
                } else {
                    // Actualizar el item específico
                    $stmt = $pdo->prepare("
                        UPDATE venta_items 
                        SET dias_credito = :dias_credito
                        WHERE id = :item_id 
                        AND estado = 'COMPLETADO'
                    ");
                    
                    $stmt->execute([
                        ':dias_credito' => $cuota_item['dias_credito'],
                        ':item_id' => $cuota_item['item_id']
                    ]);
                }
            }
        }
    }

    // Confirmar la transacción
    $pdo->commit();
    
    // Una vez confirmada la transacción, consultar venta_items para obtener los montos reales
    try {
        // Obtener el total de ventas a contado
        $stmt_contado = $pdo->prepare("
            SELECT SUM(subtotal) as total_contado 
            FROM venta_items 
            WHERE venta_id = :venta_id 
            AND tipo_venta = 'contado'
            AND estado = 'COMPLETADO'
        ");
        $stmt_contado->execute([':venta_id' => $num_venta]);
        $result_contado = $stmt_contado->fetch(PDO::FETCH_ASSOC);
        $total_contado = $result_contado && isset($result_contado['total_contado']) ? floatval($result_contado['total_contado']) : 0;
        
        // Obtener el total de primeras cuotas de productos a crédito
        $stmt_credito = $pdo->prepare("
            SELECT SUM(monto_primera_cuota) as total_credito_inicial
            FROM venta_items 
            WHERE venta_id = :venta_id 
            AND tipo_venta = 'credito'
            AND primera_cuota = 1
            AND estado = 'COMPLETADO'
        ");
        $stmt_credito->execute([':venta_id' => $num_venta]);
        $result_credito = $stmt_credito->fetch(PDO::FETCH_ASSOC);
        $total_credito_inicial = $result_credito && isset($result_credito['total_credito_inicial']) ? floatval($result_credito['total_credito_inicial']) : 0;
        
        // Recalcular el total de efectivo recibido
        $total_efectivo = $total_contado + $total_credito_inicial;
        

    } catch (Exception $e) {
        error_log("Error al obtener montos desde venta_items: " . $e->getMessage());
        // Si hay error, se mantienen los cálculos originales
    }
    
    // Registrar la actividad en un proceso separado después de la transacción exitosa
    $info_venta = [
        'cliente_id' => $cliente_id,
        'cliente_nombre' => $cliente_nombre,
        'cliente_documento' => $cliente_documento,
        'num_venta' => $num_venta,
        'total_venta' => $total_venta,
        'productos' => $productos_nombres,
        'productos_detallados' => $productos_detallados,
        'tipo_venta' => $tipo_venta_general,
        'primera_cuota' => $hay_primera_cuota ? 1 : 0,
        'monto_primera_cuota' => $total_credito_inicial, // Actualizado con datos de la BD
        'entrega_inicial' => $entrega_inicial,     // Agregar la entrega inicial
        'total_efectivo' => $total_efectivo,        // Actualizado con datos de la BD
        'total_contado' => $total_contado          // Actualizado con datos de la BD
    ];
    
    // Registrar actividad de venta finalizada
    registrar_actividad_venta($usuario_id, $info_venta);
    
    $response['success'] = true;
    $response['message'] = 'Venta finalizada con éxito';
    //$response['print_url'] = "imprimir_boleta.php?venta_id=" . urlencode($num_venta); // Agregar esta línea
    
    // // Justo antes del echo json_encode($response)
    // error_log("Número de venta generado: " . $num_venta);
    // $response['success'] = true;
    // $response['message'] = 'Venta finalizada con éxito';
    //$response['print_url'] = "imprimir_boleta.php?venta_id=" . urlencode($num_venta);
    //$response['venta_id'] = $num_venta; // Agregar esto para depuración
    
    // Agregar mensaje de depuración antes del acceso
    //error_log("hola Verificando venta_id en item: " . urlencode($num_venta));
    // Intentar imprimir la boleta automáticamente
    
} catch (Exception $e) {
    // Revertir cambios si hay error
    if ($pdo->inTransaction()) {
        // Reactivar la verificación de claves foráneas antes de hacer rollback
        $pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
        $pdo->rollBack();
    }
    $response['message'] = 'Error al procesar la venta: ' . $e->getMessage();
    
    // Registrar el error en el historial de actividades
    registrar_actividad_error($usuario_id, 'Error al finalizar venta: ' . $e->getMessage());
}

header('Content-Type: application/json');
echo json_encode($response);
?>
