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

$user = requireAuth();

switch ($tipo) {
    case 'getRutas':
        try {
            $fecha = $datapost['fecha'] ?? $_GET['fecha'] ?? date('Y-m-d');
            $fecha_inicio = $datapost['fecha_inicio'] ?? $_GET['fecha_inicio'] ?? $fecha;
            $fecha_fin = $datapost['fecha_fin'] ?? $_GET['fecha_fin'] ?? $fecha;

            $query = "SELECT r.*,
                     (SELECT COUNT(*) FROM ruta_pedidos WHERE ruta_id = r.id) as total_pedidos,
                     (SELECT COALESCE(SUM(v.total), 0) FROM ruta_pedidos rp JOIN ventas v ON rp.venta_id = v.id WHERE rp.ruta_id = r.id) as monto_total
                     FROM rutas_entrega r
                     WHERE r.fecha BETWEEN ? AND ?
                     ORDER BY r.fecha ASC, r.created_at ASC";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("ss", $fecha_inicio, $fecha_fin);
            $stmt->execute();
            $result = $stmt->get_result();

            $rutas = [];
            while ($row = $result->fetch_assoc()) {
                $rutas[] = [
                    'id' => intval($row['id']),
                    'nombre' => $row['nombre'],
                    'fecha' => $row['fecha'],
                    'estado' => $row['estado'],
                    'total_pedidos' => intval($row['total_pedidos']),
                    'monto_total' => floatval($row['monto_total']),
                    'created_at' => $row['created_at']
                ];
            }

            sendResponse(true, "Rutas obtenidas", $rutas);

        } catch (Exception $e) {
            sendResponse(false, "Error al obtener rutas: " . $e->getMessage());
        }
        break;

    case 'getRuta':
        $id = intval($datapost['id'] ?? $_GET['id'] ?? 0);

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

        try {
            $rutaStmt = $conn->prepare("SELECT * FROM rutas_entrega WHERE id = ?");
            $rutaStmt->bind_param("i", $id);
            $rutaStmt->execute();
            $ruta = $rutaStmt->get_result()->fetch_assoc();

            if (!$ruta) {
                sendResponse(false, "Ruta no encontrada");
            }

            // Obtener pedidos con coordenadas y teléfonos
            $pedidosQuery = "SELECT
                rp.id as ruta_pedido_id,
                rp.orden,
                rp.venta_id,
                v.folio,
                v.cliente_id,
                v.cliente_nombre,
                v.direccion_entrega,
                v.total,
                v.metodo_pago,
                v.estatus_pago,
                v.saldo_pendiente,
                v.tipo_entrega,
                v.estado,
                v.fecha_creacion,
                cd.latitud,
                cd.longitud,
                (SELECT GROUP_CONCAT(ct.telefono SEPARATOR ', ')
                 FROM cliente_telefonos ct
                 WHERE ct.cliente_id = v.cliente_id AND ct.activo = 1) as telefonos
            FROM ruta_pedidos rp
            INNER JOIN ventas v ON rp.venta_id = v.id
            LEFT JOIN cliente_direcciones cd ON v.cliente_id = cd.cliente_id
                AND cd.direccion = v.direccion_entrega
                AND cd.activo = 1
            WHERE rp.ruta_id = ?
            ORDER BY rp.orden ASC";

            $pedStmt = $conn->prepare($pedidosQuery);
            $pedStmt->bind_param("i", $id);
            $pedStmt->execute();
            $pedResult = $pedStmt->get_result();

            $pedidos = [];
            $monto_total = 0;
            $monto_cobrado = 0;
            $monto_pendiente = 0;

            while ($row = $pedResult->fetch_assoc()) {
                $total = floatval($row['total']);
                $saldo = floatval($row['saldo_pendiente'] ?? 0);
                $monto_total += $total;

                if ($row['estatus_pago'] === 'pagado') {
                    $monto_cobrado += $total;
                } else {
                    $monto_pendiente += $saldo > 0 ? $saldo : $total;
                }

                $pedidos[] = [
                    'ruta_pedido_id' => intval($row['ruta_pedido_id']),
                    'orden' => intval($row['orden']),
                    'venta_id' => intval($row['venta_id']),
                    'folio' => $row['folio'],
                    'cliente_id' => $row['cliente_id'] ? intval($row['cliente_id']) : null,
                    'cliente_nombre' => $row['cliente_nombre'],
                    'direccion_entrega' => $row['direccion_entrega'],
                    'total' => $total,
                    'metodo_pago' => $row['metodo_pago'],
                    'estatus_pago' => $row['estatus_pago'],
                    'saldo_pendiente' => $saldo,
                    'tipo_entrega' => $row['tipo_entrega'],
                    'estado' => $row['estado'],
                    'latitud' => $row['latitud'] ? floatval($row['latitud']) : null,
                    'longitud' => $row['longitud'] ? floatval($row['longitud']) : null,
                    'telefonos' => $row['telefonos'],
                    'fecha_creacion' => $row['fecha_creacion']
                ];
            }

            $rutaData = [
                'id' => intval($ruta['id']),
                'nombre' => $ruta['nombre'],
                'fecha' => $ruta['fecha'],
                'estado' => $ruta['estado'],
                'pedidos' => $pedidos,
                'resumen' => [
                    'total_pedidos' => count($pedidos),
                    'monto_total' => round($monto_total, 2),
                    'monto_cobrado' => round($monto_cobrado, 2),
                    'monto_pendiente' => round($monto_pendiente, 2)
                ],
                'created_at' => $ruta['created_at']
            ];

            sendResponse(true, "Ruta obtenida", $rutaData);

        } catch (Exception $e) {
            sendResponse(false, "Error al obtener ruta: " . $e->getMessage());
        }
        break;

    case 'getPedidosRuta':
        $ruta_id = intval($datapost['ruta_id'] ?? $_GET['ruta_id'] ?? 0);

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

        try {
            $query = "SELECT
                rp.id as ruta_pedido_id,
                rp.orden,
                rp.venta_id,
                v.folio,
                v.cliente_id,
                v.cliente_nombre,
                v.direccion_entrega,
                v.total,
                v.metodo_pago,
                v.estatus_pago,
                v.saldo_pendiente,
                v.estado,
                cd.latitud,
                cd.longitud,
                (SELECT GROUP_CONCAT(ct.telefono SEPARATOR ', ')
                 FROM cliente_telefonos ct
                 WHERE ct.cliente_id = v.cliente_id AND ct.activo = 1) as telefonos
            FROM ruta_pedidos rp
            INNER JOIN ventas v ON rp.venta_id = v.id
            LEFT JOIN cliente_direcciones cd ON v.cliente_id = cd.cliente_id
                AND cd.direccion = v.direccion_entrega
                AND cd.activo = 1
            WHERE rp.ruta_id = ?
            ORDER BY rp.orden ASC";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $ruta_id);
            $stmt->execute();
            $result = $stmt->get_result();

            $pedidos = [];
            while ($row = $result->fetch_assoc()) {
                $pedidos[] = [
                    'ruta_pedido_id' => intval($row['ruta_pedido_id']),
                    'orden' => intval($row['orden']),
                    'venta_id' => intval($row['venta_id']),
                    'folio' => $row['folio'],
                    'cliente_id' => $row['cliente_id'] ? intval($row['cliente_id']) : null,
                    'cliente_nombre' => $row['cliente_nombre'],
                    'direccion_entrega' => $row['direccion_entrega'],
                    'total' => floatval($row['total']),
                    'metodo_pago' => $row['metodo_pago'],
                    'estatus_pago' => $row['estatus_pago'],
                    'saldo_pendiente' => floatval($row['saldo_pendiente'] ?? 0),
                    'estado' => $row['estado'],
                    'latitud' => $row['latitud'] ? floatval($row['latitud']) : null,
                    'longitud' => $row['longitud'] ? floatval($row['longitud']) : null,
                    'telefonos' => $row['telefonos']
                ];
            }

            sendResponse(true, "Pedidos de ruta obtenidos", $pedidos);

        } catch (Exception $e) {
            sendResponse(false, "Error al obtener pedidos de ruta: " . $e->getMessage());
        }
        break;

    case 'actualizarEstadoEntrega':
        $venta_id = intval($datapost['venta_id'] ?? 0);
        $estado = trim($datapost['estado'] ?? '');
        $observaciones = trim($datapost['observaciones'] ?? '');
        $latitud = isset($datapost['latitud']) ? floatval($datapost['latitud']) : null;
        $longitud = isset($datapost['longitud']) ? floatval($datapost['longitud']) : null;

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

        $estados_validos = ['entregado', 'no_entregado', 'reprogramado'];
        if (!in_array($estado, $estados_validos)) {
            sendResponse(false, "Estado no válido. Valores permitidos: " . implode(', ', $estados_validos));
        }

        try {
            $conn->begin_transaction();

            // Actualizar estado de la venta
            $nuevoEstadoVenta = $estado === 'entregado' ? 'entregado' : $estado;
            $updateStmt = $conn->prepare("UPDATE ventas SET estado = ? WHERE id = ?");
            $updateStmt->bind_param("si", $nuevoEstadoVenta, $venta_id);

            if (!$updateStmt->execute()) {
                $conn->rollback();
                sendResponse(false, "Error al actualizar estado de entrega");
            }

            // Agregar observaciones si hay
            if (!empty($observaciones)) {
                $obsStmt = $conn->prepare("UPDATE ventas SET observaciones = CONCAT(COALESCE(observaciones, ''), '\nENTREGA: ', ?) WHERE id = ?");
                $obsStmt->bind_param("si", $observaciones, $venta_id);
                $obsStmt->execute();
            }

            // Registrar log de entrega con GPS
            $logStmt = $conn->prepare("INSERT INTO log_actividad (usuario_id, accion, detalles, fecha) VALUES (?, ?, ?, NOW())");
            if ($logStmt) {
                $accion = "entrega_" . $estado;
                $detalles = json_encode([
                    'venta_id' => $venta_id,
                    'estado' => $estado,
                    'latitud' => $latitud,
                    'longitud' => $longitud,
                    'observaciones' => $observaciones
                ]);
                $logStmt->bind_param("iss", $user['id'], $accion, $detalles);
                $logStmt->execute();
            }

            $conn->commit();
            sendResponse(true, "Estado de entrega actualizado", [
                'venta_id' => $venta_id,
                'estado' => $estado
            ]);

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al actualizar estado de entrega: " . $e->getMessage());
        }
        break;

    case 'cobrarEntrega':
        $venta_id = intval($datapost['venta_id'] ?? 0);
        $monto = floatval($datapost['monto'] ?? 0);
        $metodo_pago = trim($datapost['metodo_pago'] ?? 'efectivo');
        $referencia = trim($datapost['referencia'] ?? '');
        $latitud = isset($datapost['latitud']) ? floatval($datapost['latitud']) : null;
        $longitud = isset($datapost['longitud']) ? floatval($datapost['longitud']) : null;

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

        if ($monto <= 0) {
            sendResponse(false, "El monto debe ser mayor a 0");
        }

        try {
            $ventaStmt = $conn->prepare("SELECT total, saldo_pendiente, estatus_pago, cliente_id, metodo_pago FROM ventas WHERE id = ? AND estado != 'cancelada'");
            $ventaStmt->bind_param("i", $venta_id);
            $ventaStmt->execute();
            $ventaResult = $ventaStmt->get_result();

            if ($ventaResult->num_rows === 0) {
                sendResponse(false, "Venta no encontrada o cancelada");
            }

            $venta = $ventaResult->fetch_assoc();
            $saldo_actual = floatval($venta['saldo_pendiente'] ?? $venta['total']);

            $conn->begin_transaction();

            // Registrar pago
            $pagoStmt = $conn->prepare("INSERT INTO venta_pagos (venta_id, monto, metodo_pago, referencia, usuario_id) VALUES (?, ?, ?, ?, ?)");
            if ($pagoStmt) {
                $pagoStmt->bind_param("idssi", $venta_id, $monto, $metodo_pago, $referencia, $user['id']);
                $pagoStmt->execute();
            }

            // Actualizar saldo
            $nuevo_saldo = max(0, $saldo_actual - $monto);
            $nuevo_estatus = $nuevo_saldo <= 0.01 ? 'pagado' : 'pendiente';

            $updateStmt = $conn->prepare("UPDATE ventas SET saldo_pendiente = ?, estatus_pago = ? WHERE id = ?");
            $updateStmt->bind_param("dsi", $nuevo_saldo, $nuevo_estatus, $venta_id);
            $updateStmt->execute();

            // Actualizar crédito si es pago completo
            if ($nuevo_estatus === 'pagado' && $venta['metodo_pago'] === 'credito' && $venta['cliente_id']) {
                $totalVenta = floatval($venta['total']);
                $creditoStmt = $conn->prepare("UPDATE clientes SET saldo_credito_usado = GREATEST(0, saldo_credito_usado - ?) WHERE id = ?");
                $creditoStmt->bind_param("di", $totalVenta, $venta['cliente_id']);
                $creditoStmt->execute();
            }

            // Log con GPS
            $logStmt = $conn->prepare("INSERT INTO log_actividad (usuario_id, accion, detalles, fecha) VALUES (?, ?, ?, NOW())");
            if ($logStmt) {
                $accion = "cobro_entrega";
                $detalles = json_encode([
                    'venta_id' => $venta_id,
                    'monto' => $monto,
                    'metodo_pago' => $metodo_pago,
                    'latitud' => $latitud,
                    'longitud' => $longitud
                ]);
                $logStmt->bind_param("iss", $user['id'], $accion, $detalles);
                $logStmt->execute();
            }

            $conn->commit();

            $cambio = max(0, $monto - $saldo_actual);

            sendResponse(true, "Cobro registrado exitosamente", [
                'venta_id' => $venta_id,
                'monto_cobrado' => $monto,
                'saldo_pendiente' => round($nuevo_saldo, 2),
                'estatus_pago' => $nuevo_estatus,
                'cambio' => round($cambio, 2)
            ]);

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al cobrar entrega: " . $e->getMessage());
        }
        break;

    case 'calcularFlete':
        $distancia_km = floatval($datapost['distancia_km'] ?? 0);
        $vehiculo_id = intval($datapost['vehiculo_id'] ?? 0);

        if ($distancia_km <= 0) {
            sendResponse(false, "La distancia debe ser mayor a 0");
        }

        try {
            // Buscar rango de flete aplicable
            $query = "SELECT id, distancia_min, distancia_max, costo_fijo, costo_por_km
                     FROM rangos_flete
                     WHERE activo = 1
                     AND distancia_min <= ?
                     AND (distancia_max IS NULL OR distancia_max >= ?)
                     ORDER BY distancia_min ASC
                     LIMIT 1";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("dd", $distancia_km, $distancia_km);
            $stmt->execute();
            $result = $stmt->get_result();

            if ($rango = $result->fetch_assoc()) {
                $costo_fijo = floatval($rango['costo_fijo']);
                $costo_por_km = floatval($rango['costo_por_km']);
                $costo_total = $costo_fijo + ($costo_por_km * $distancia_km);

                // Si hay vehículo, buscar costo adicional
                $costo_vehiculo = 0;
                if ($vehiculo_id > 0) {
                    $vehStmt = $conn->prepare("SELECT costo_por_km FROM vehiculos WHERE id = ? AND activo = 1");
                    if ($vehStmt) {
                        $vehStmt->bind_param("i", $vehiculo_id);
                        $vehStmt->execute();
                        $vehResult = $vehStmt->get_result();
                        if ($veh = $vehResult->fetch_assoc()) {
                            $costo_vehiculo = floatval($veh['costo_por_km']) * $distancia_km;
                        }
                    }
                }

                sendResponse(true, "Flete calculado", [
                    'distancia_km' => $distancia_km,
                    'rango_aplicado' => [
                        'id' => intval($rango['id']),
                        'distancia_min' => floatval($rango['distancia_min']),
                        'distancia_max' => $rango['distancia_max'] ? floatval($rango['distancia_max']) : null,
                        'costo_fijo' => $costo_fijo,
                        'costo_por_km' => $costo_por_km
                    ],
                    'costo_base' => round($costo_total, 2),
                    'costo_vehiculo' => round($costo_vehiculo, 2),
                    'costo_total' => round($costo_total + $costo_vehiculo, 2)
                ]);
            } else {
                // Sin rango definido, retornar costo 0
                sendResponse(true, "No hay rango de flete definido para esta distancia", [
                    'distancia_km' => $distancia_km,
                    'rango_aplicado' => null,
                    'costo_base' => 0,
                    'costo_vehiculo' => 0,
                    'costo_total' => 0
                ]);
            }

        } catch (Exception $e) {
            sendResponse(false, "Error al calcular flete: " . $e->getMessage());
        }
        break;

    default:
        sendResponse(false, "Operación no válida para logística");
        break;
}
