<?php

/**
 * Cambios.php - Manejo de cambios de productos (garantías/reemplazos)
 * Sistema para intercambio directo de productos defectuosos por nuevos
 */

// Función para enviar respuesta JSON
if (!function_exists('sendResponse')) {
    function sendResponse($success, $message = '', $data = null)
    {
        echo json_encode([
            "success" => $success,
            "message" => $message,
            "data" => $data
        ]);
        exit;
    }
}

// === REGISTRAR CAMBIO ===
if ($tipo === 'registrarCambio') {
    error_log("=== REGISTRANDO CAMBIO ===");

    // Obtener token del repartidor
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (empty($authHeader)) {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
    }

    if (empty($authHeader)) {
        sendResponse(false, "Token de autenticación requerido");
    }

    $token = str_replace('Bearer ', '', $authHeader);

    // Verificar token y obtener repartidor_id
    require_once __DIR__ . '/../../modelos/Auth.php';
    $auth = new Auth($conn);
    $payload = $auth->verificarJWT($token);

    if (!$payload) {
        sendResponse(false, "Token inválido o expirado");
    }

    $repartidorId = $payload['repartidor_id'] ?? null;
    if (!$repartidorId) {
        sendResponse(false, "Token no válido para repartidor");
    }

    // Obtener parámetros
    $clienteId = isset($datapost['cliente_id']) ? (int)$datapost['cliente_id'] : 0;
    $visitaId = isset($datapost['visita_id']) ? (int)$datapost['visita_id'] : null;
    $productos = isset($datapost['productos']) ? $datapost['productos'] : [];
    $notas = isset($datapost['notas']) ? $datapost['notas'] : '';

    if ($clienteId <= 0) {
        sendResponse(false, "ID de cliente requerido");
    }

    if (empty($productos)) {
        sendResponse(false, "Debe incluir al menos un producto para cambiar");
    }

    try {
        error_log("Registrando cambio: Cliente ID=$clienteId, Productos=" . count($productos));

        // Iniciar transacción
        $conn->beginTransaction();

        // Crear registro de cambio
        $queryCambio = "INSERT INTO cambios (
                            repartidor_id,
                            cliente_id,
                            visita_id,
                            fecha_cambio,
                            hora_cambio,
                            estado,
                            notas,
                            created_at
                        ) VALUES (
                            :repartidor_id,
                            :cliente_id,
                            :visita_id,
                            CURDATE(),
                            CURTIME(),
                            'completado',
                            :notas,
                            NOW()
                        )";

        $stmtCambio = $conn->prepare($queryCambio);
        $stmtCambio->bindParam(':repartidor_id', $repartidorId);
        $stmtCambio->bindParam(':cliente_id', $clienteId);
        $stmtCambio->bindParam(':visita_id', $visitaId);
        $stmtCambio->bindParam(':notas', $notas);
        $stmtCambio->execute();

        $cambioId = $conn->lastInsertId();

        // Obtener el folio generado por el trigger (o generar uno manual)
        $queryFolio = "SELECT folio FROM cambios WHERE id = :id";
        $stmtFolio = $conn->prepare($queryFolio);
        $stmtFolio->bindParam(':id', $cambioId);
        $stmtFolio->execute();
        $folio = $stmtFolio->fetchColumn();

        // Si no hay trigger, generar folio manualmente
        if (empty($folio)) {
            $folio = 'CAM-' . str_pad($cambioId, 6, '0', STR_PAD_LEFT);
            $queryUpdateFolio = "UPDATE cambios SET folio = :folio WHERE id = :id";
            $stmtUpdateFolio = $conn->prepare($queryUpdateFolio);
            $stmtUpdateFolio->bindParam(':folio', $folio);
            $stmtUpdateFolio->bindParam(':id', $cambioId);
            $stmtUpdateFolio->execute();
        }

        error_log("Cambio creado con ID: $cambioId, Folio: $folio");

        // Insertar detalles de cambio y actualizar inventario
        foreach ($productos as $producto) {
            $productoId = (int)$producto['producto_id'];
            $cantidad = (float)$producto['cantidad'];
            $motivo = isset($producto['motivo']) ? $producto['motivo'] : 'defectuoso';
            $descripcionMotivo = isset($producto['descripcion_motivo']) ? $producto['descripcion_motivo'] : '';

            // Validar motivo
            $motivosValidos = ['defectuoso', 'dañado', 'caducado'];
            if (!in_array($motivo, $motivosValidos)) {
                $motivo = 'defectuoso';
            }

            // Insertar detalle
            $queryDetalle = "INSERT INTO cambios_detalle (
                                cambio_id,
                                producto_id,
                                cantidad,
                                motivo,
                                descripcion_motivo,
                                created_at
                            ) VALUES (
                                :cambio_id,
                                :producto_id,
                                :cantidad,
                                :motivo,
                                :descripcion_motivo,
                                NOW()
                            )";

            $stmtDetalle = $conn->prepare($queryDetalle);
            $stmtDetalle->bindParam(':cambio_id', $cambioId);
            $stmtDetalle->bindParam(':producto_id', $productoId);
            $stmtDetalle->bindParam(':cantidad', $cantidad);
            $stmtDetalle->bindParam(':motivo', $motivo);
            $stmtDetalle->bindParam(':descripcion_motivo', $descripcionMotivo);
            $stmtDetalle->execute();

            error_log("Detalle insertado: Producto ID=$productoId, Cantidad=$cantidad");

            // Actualizar inventario del repartidor:
            // 1. Restar del inventario normal (producto defectuoso recibido)
            // 2. Agregar al inventario de devoluciones (producto defectuoso)
            // 3. El producto nuevo que entrega ya está en su inventario, no se suma

            error_log("Actualizando inventarios para cambio - Producto ID=$productoId, Cantidad=$cantidad");

            // 1. RESTAR del inventario NORMAL (producto defectuoso que recibe del cliente)
            $queryRestarInventarioNormal = "UPDATE inventarios_repartidor
                                           SET cantidad = cantidad - :cantidad,
                                               updated_at = NOW()
                                           WHERE repartidor_id = :repartidor_id
                                             AND producto_id = :producto_id";

            $stmtRestarNormal = $conn->prepare($queryRestarInventarioNormal);
            $stmtRestarNormal->bindParam(':cantidad', $cantidad);
            $stmtRestarNormal->bindParam(':repartidor_id', $repartidorId);
            $stmtRestarNormal->bindParam(':producto_id', $productoId);
            $stmtRestarNormal->execute();

            // Si el producto no existe en inventario normal, crear con cantidad negativa
            if ($stmtRestarNormal->rowCount() === 0) {
                error_log("⚠️ Producto ID=$productoId no existe en inventario normal, creando con cantidad negativa");
                $cantidadNegativa = -$cantidad;
                $queryInsertInventarioNormal = "INSERT INTO inventarios_repartidor (
                                                    repartidor_id,
                                                    producto_id,
                                                    cantidad,
                                                    created_at,
                                                    updated_at
                                                 ) VALUES (
                                                    :repartidor_id,
                                                    :producto_id,
                                                    :cantidad_negativa,
                                                    NOW(),
                                                    NOW()
                                                 )";
                $stmtInsertNormal = $conn->prepare($queryInsertInventarioNormal);
                $stmtInsertNormal->bindParam(':repartidor_id', $repartidorId);
                $stmtInsertNormal->bindParam(':producto_id', $productoId);
                $stmtInsertNormal->bindParam(':cantidad_negativa', $cantidadNegativa);
                $stmtInsertNormal->execute();
            }

            error_log("✅ Inventario normal actualizado: -$cantidad unidades");

            // 2. SUMAR al inventario de DEVOLUCIONES (producto defectuoso)
            $queryAgregarDevolucion = "UPDATE inventarios_devoluciones_repartidor
                                       SET cantidad = cantidad + :cantidad,
                                           ultimo_motivo = :motivo,
                                           fecha_ultima_devolucion = NOW(),
                                           updated_at = NOW()
                                       WHERE repartidor_id = :repartidor_id
                                         AND producto_id = :producto_id";

            $stmtAgregarDev = $conn->prepare($queryAgregarDevolucion);
            $stmtAgregarDev->bindParam(':cantidad', $cantidad);
            $stmtAgregarDev->bindParam(':motivo', $motivo);
            $stmtAgregarDev->bindParam(':repartidor_id', $repartidorId);
            $stmtAgregarDev->bindParam(':producto_id', $productoId);
            $stmtAgregarDev->execute();

            // Si el producto no existe en inventario de devoluciones, crear registro
            if ($stmtAgregarDev->rowCount() === 0) {
                error_log("Producto ID=$productoId no existe en inventario de devoluciones, creando registro");
                $queryInsertDev = "INSERT INTO inventarios_devoluciones_repartidor (
                                      repartidor_id,
                                      producto_id,
                                      cantidad,
                                      ultimo_motivo,
                                      fecha_ultima_devolucion,
                                      created_at,
                                      updated_at
                                   ) VALUES (
                                      :repartidor_id,
                                      :producto_id,
                                      :cantidad,
                                      :motivo,
                                      NOW(),
                                      NOW(),
                                      NOW()
                                   )";
                $stmtInsertDev = $conn->prepare($queryInsertDev);
                $stmtInsertDev->bindParam(':repartidor_id', $repartidorId);
                $stmtInsertDev->bindParam(':producto_id', $productoId);
                $stmtInsertDev->bindParam(':cantidad', $cantidad);
                $stmtInsertDev->bindParam(':motivo', $motivo);
                $stmtInsertDev->execute();
            }

            error_log("✅ Inventario de devoluciones actualizado: +$cantidad unidades");

            // 3. Registrar movimiento de cambio
            $queryMovimiento = "INSERT INTO movimientos_inventario_repartidor (
                                    repartidor_id,
                                    producto_id,
                                    cantidad,
                                    tipo_movimiento,
                                    notas,
                                    created_at
                                ) VALUES (
                                    :repartidor_id,
                                    :producto_id,
                                    :cantidad,
                                    'devolucion',
                                    :notas,
                                    NOW()
                                )";

            $stmtMovimiento = $conn->prepare($queryMovimiento);
            $stmtMovimiento->bindParam(':repartidor_id', $repartidorId);
            $stmtMovimiento->bindParam(':producto_id', $productoId);
            $stmtMovimiento->bindParam(':cantidad', $cantidad);
            $notasMovimiento = "CAMBIO/GARANTÍA - Folio: $folio - Motivo: $motivo - Producto defectuoso recibido del cliente";
            $stmtMovimiento->bindParam(':notas', $notasMovimiento);
            $stmtMovimiento->execute();

            error_log("✅ Movimiento de cambio registrado para producto ID=$productoId");
        }

        // Commit de la transacción
        $conn->commit();

        error_log("✅ Cambio registrado exitosamente: $folio");

        sendResponse(true, "Cambio registrado exitosamente", [
            'cambio_id' => $cambioId,
            'folio' => $folio,
            'productos_cambiados' => count($productos)
        ]);
    } catch (Exception $e) {
        // Rollback en caso de error
        if ($conn->inTransaction()) {
            $conn->rollBack();
        }

        error_log("❌ Error registrando cambio: " . $e->getMessage());
        sendResponse(false, "Error al registrar cambio: " . $e->getMessage());
    }
}

// === OBTENER HISTORIAL DE CAMBIOS ===
if ($tipo === 'getHistorialCambios') {
    error_log("=== GET HISTORIAL CAMBIOS ===");

    // Obtener token del repartidor
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (empty($authHeader)) {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
    }

    if (empty($authHeader)) {
        sendResponse(false, "Token de autenticación requerido");
    }

    $token = str_replace('Bearer ', '', $authHeader);

    // Verificar token
    require_once __DIR__ . '/../../modelos/Auth.php';
    $auth = new Auth($conn);
    $payload = $auth->verificarJWT($token);

    if (!$payload) {
        sendResponse(false, "Token inválido o expirado");
    }

    $repartidorId = $payload['repartidor_id'] ?? null;
    if (!$repartidorId) {
        sendResponse(false, "Token no válido para repartidor");
    }

    // Parámetros de filtro
    $fechaInicio = isset($datapost['fecha_inicio']) ? $datapost['fecha_inicio'] : null;
    $fechaFin = isset($datapost['fecha_fin']) ? $datapost['fecha_fin'] : null;
    $clienteId = isset($datapost['cliente_id']) ? (int)$datapost['cliente_id'] : null;
    $limite = isset($datapost['limite']) ? (int)$datapost['limite'] : 50;

    try {
        $query = "SELECT
                    c.id,
                    c.folio,
                    c.cliente_id,
                    cl.nombre_comercial as cliente_nombre,
                    c.fecha_cambio,
                    c.hora_cambio,
                    c.estado,
                    c.notas,
                    COUNT(cd.id) as total_productos,
                    c.created_at
                FROM cambios c
                LEFT JOIN clientes cl ON c.cliente_id = cl.id
                LEFT JOIN cambios_detalle cd ON c.id = cd.cambio_id
                WHERE c.repartidor_id = :repartidor_id";

        if ($fechaInicio) {
            $query .= " AND c.fecha_cambio >= :fecha_inicio";
        }

        if ($fechaFin) {
            $query .= " AND c.fecha_cambio <= :fecha_fin";
        }

        if ($clienteId) {
            $query .= " AND c.cliente_id = :cliente_id";
        }

        $query .= " GROUP BY c.id
                   ORDER BY c.fecha_cambio DESC, c.hora_cambio DESC
                   LIMIT :limite";

        $stmt = $conn->prepare($query);
        $stmt->bindParam(':repartidor_id', $repartidorId);

        if ($fechaInicio) {
            $stmt->bindParam(':fecha_inicio', $fechaInicio);
        }

        if ($fechaFin) {
            $stmt->bindParam(':fecha_fin', $fechaFin);
        }

        if ($clienteId) {
            $stmt->bindParam(':cliente_id', $clienteId);
        }

        $stmt->bindParam(':limite', $limite, PDO::PARAM_INT);
        $stmt->execute();

        $cambios = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Obtener productos para cada cambio
        foreach ($cambios as &$cambio) {
            $queryProductos = "SELECT
                                cd.id,
                                cd.producto_id,
                                p.codigo,
                                p.nombre as producto_nombre,
                                cd.cantidad,
                                cd.motivo,
                                cd.descripcion_motivo
                            FROM cambios_detalle cd
                            LEFT JOIN productos p ON cd.producto_id = p.id
                            WHERE cd.cambio_id = :cambio_id";

            $stmtProd = $conn->prepare($queryProductos);
            $stmtProd->bindParam(':cambio_id', $cambio['id']);
            $stmtProd->execute();
            $cambio['productos'] = $stmtProd->fetchAll(PDO::FETCH_ASSOC);
        }

        sendResponse(true, "Historial de cambios obtenido", $cambios);
    } catch (Exception $e) {
        error_log("Error obteniendo historial de cambios: " . $e->getMessage());
        sendResponse(false, "Error al obtener historial: " . $e->getMessage());
    }
}

// === OBTENER DETALLE DE CAMBIO ===
if ($tipo === 'getDetalleCambio') {
    error_log("=== GET DETALLE CAMBIO ===");

    // Obtener token del repartidor
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (empty($authHeader)) {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
    }

    if (empty($authHeader)) {
        sendResponse(false, "Token de autenticación requerido");
    }

    $token = str_replace('Bearer ', '', $authHeader);

    // Verificar token
    require_once __DIR__ . '/../../modelos/Auth.php';
    $auth = new Auth($conn);
    $payload = $auth->verificarJWT($token);

    if (!$payload) {
        sendResponse(false, "Token inválido o expirado");
    }

    $cambioId = isset($datapost['cambio_id']) ? (int)$datapost['cambio_id'] : 0;

    if ($cambioId <= 0) {
        sendResponse(false, "ID de cambio requerido");
    }

    try {
        // Obtener datos del cambio
        $queryCambio = "SELECT
                        c.id,
                        c.folio,
                        c.repartidor_id,
                        c.cliente_id,
                        cl.nombre_comercial as cliente_nombre,
                        cl.direccion as cliente_direccion,
                        c.fecha_cambio,
                        c.hora_cambio,
                        c.estado,
                        c.notas,
                        r.nombre as repartidor_nombre,
                        c.created_at
                    FROM cambios c
                    LEFT JOIN clientes cl ON c.cliente_id = cl.id
                    LEFT JOIN repartidores r ON c.repartidor_id = r.id
                    WHERE c.id = :cambio_id";

        $stmtCambio = $conn->prepare($queryCambio);
        $stmtCambio->bindParam(':cambio_id', $cambioId);
        $stmtCambio->execute();

        $cambio = $stmtCambio->fetch(PDO::FETCH_ASSOC);

        if (!$cambio) {
            sendResponse(false, "Cambio no encontrado");
        }

        // Obtener productos del cambio
        $queryProductos = "SELECT
                            cd.id,
                            cd.producto_id,
                            p.codigo,
                            p.nombre,
                            cd.cantidad,
                            cd.motivo,
                            cd.descripcion_motivo
                        FROM cambios_detalle cd
                        LEFT JOIN productos p ON cd.producto_id = p.id
                        WHERE cd.cambio_id = :cambio_id";

        $stmtProductos = $conn->prepare($queryProductos);
        $stmtProductos->bindParam(':cambio_id', $cambioId);
        $stmtProductos->execute();

        $productos = $stmtProductos->fetchAll(PDO::FETCH_ASSOC);

        $cambio['productos'] = $productos;

        sendResponse(true, "Detalle de cambio obtenido", $cambio);
    } catch (Exception $e) {
        error_log("Error obteniendo detalle de cambio: " . $e->getMessage());
        sendResponse(false, "Error al obtener detalle: " . $e->getMessage());
    }
}

// === CANCELAR CAMBIO ===
if ($tipo === 'cancelarCambio') {
    error_log("=== CANCELAR CAMBIO ===");

    // Obtener token del repartidor
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (empty($authHeader)) {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
    }

    if (empty($authHeader)) {
        sendResponse(false, "Token de autenticación requerido");
    }

    $token = str_replace('Bearer ', '', $authHeader);

    // Verificar token
    require_once __DIR__ . '/../../modelos/Auth.php';
    $auth = new Auth($conn);
    $payload = $auth->verificarJWT($token);

    if (!$payload) {
        sendResponse(false, "Token inválido o expirado");
    }

    $cambioId = isset($datapost['cambio_id']) ? (int)$datapost['cambio_id'] : 0;
    $motivo = isset($datapost['motivo']) ? $datapost['motivo'] : '';

    if ($cambioId <= 0) {
        sendResponse(false, "ID de cambio requerido");
    }

    try {
        // Actualizar estado del cambio
        $query = "UPDATE cambios
                 SET estado = 'cancelado',
                     notas = CONCAT(IFNULL(notas, ''), '\nCANCELADO: ', :motivo)
                 WHERE id = :cambio_id";

        $stmt = $conn->prepare($query);
        $stmt->bindParam(':cambio_id', $cambioId);
        $stmt->bindParam(':motivo', $motivo);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            sendResponse(true, "Cambio cancelado exitosamente");
        } else {
            sendResponse(false, "No se pudo cancelar el cambio");
        }
    } catch (Exception $e) {
        error_log("Error cancelando cambio: " . $e->getMessage());
        sendResponse(false, "Error al cancelar cambio: " . $e->getMessage());
    }
}
