<?php
require_once __DIR__ . '/../models/model_pedido.php';
require_once __DIR__ . '/../models/model_detalle_pedido.php';
require_once __DIR__ . '/../models/model_producto.php';
require_once __DIR__ . '/../models/model_historial.php';
require_once __DIR__ . '/../models/model_config_envio.php';
require_once __DIR__ . '/../services/PedidoEstadoHelper.php';

class CarritoController
{
    private $pedidoModel;
    private $detallePedidoModel;
    private $productoModel;
    private $historialModel;
    private $configEnvio;

    public function __construct()
    {
        $this->pedidoModel = new Pedido();
        $this->detallePedidoModel = new DetallePedido();
        $this->productoModel = new ModelProducto();
        $this->historialModel = new Historial();
        $this->configEnvio = new ModelConfigEnvio();
    }

    public function processOrder($data)
    {
        try {
            $this->validateOrderData($data);
            $pedidoData = $this->prepareOrderData($data);
            $idPedido = $this->createOrder($pedidoData);
            $this->addOrderItems($idPedido, $data['cartItems']);
            $this->createHistorialRecord($idPedido);

            return [
                'id_pedido' => $idPedido,
                'latitude' => $data['latitude'] ?? null,
                'longitude' => $data['longitude'] ?? null,
            ];
        } catch (Exception $e) {
            error_log('Error en processOrder: ' . $e->getMessage());
            throw $e;
        }
    }

    private function calcularSubtotalCarrito(string $cartItemsJson): float
    {
        $items = json_decode($cartItemsJson, true);
        if (!is_array($items)) {
            throw new Exception('Formato inválido del carrito');
        }
        $subtotal = 0.0;
        foreach ($items as $item) {
            $price = (float)($item['price'] ?? $item['precio'] ?? 0);
            $qty = (int)($item['quantity'] ?? $item['qty'] ?? $item['cantidad'] ?? 1);
            if ($qty < 1) {
                $qty = 1;
            }
            $subtotal += $price * $qty;
        }
        if ($subtotal <= 0) {
            throw new Exception('El subtotal del carrito debe ser mayor a cero');
        }
        return round($subtotal, 2);
    }

    private function validateOrderData($data)
    {
        $required = ['fullName', 'phoneNumber', 'cartItems'];
        $missing = [];
        foreach ($required as $field) {
            if (empty($data[$field])) {
                $missing[] = $field;
            }
        }
        if ($missing) {
            throw new Exception('Faltan campos obligatorios: ' . implode(', ', $missing));
        }

        if (!preg_match('/^[0-9]{10}$/', preg_replace('/\D+/', '', $data['phoneNumber']))) {
            throw new Exception('El teléfono debe tener 10 dígitos');
        }

        json_decode($data['cartItems'], true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception('Error en formato de items del carrito');
        }

        $deliveryRequested = !empty($data['deliveryRequested']) && $data['deliveryRequested'] !== '0';
        $cfg = $this->configEnvio->getConfig();

        if ($deliveryRequested) {
            if (!(int)$cfg['envio_habilitado']) {
                throw new Exception('El servicio a domicilio no está disponible en este momento');
            }
            if (empty(trim($data['addressText'] ?? ''))) {
                throw new Exception('Debes ingresar la dirección para envío a domicilio');
            }
            if (empty($data['latitude']) || empty($data['longitude'])) {
                throw new Exception('Debes seleccionar una ubicación en el mapa para envío a domicilio');
            }
        }

        $subtotal = $this->calcularSubtotalCarrito($data['cartItems']);
        $costoEnvioEsperado = 0.0;
        if ($deliveryRequested) {
            $costoEnvioEsperado = $this->configEnvio->calcularCostoEnvio($subtotal);
        }

        $totalEsperado = round($subtotal + $costoEnvioEsperado, 2);
        $totalRecibido = round((float)($data['totalAmount'] ?? 0), 2);

        if (abs($totalRecibido - $totalEsperado) > 0.02) {
            throw new Exception(
                "El total no coincide (esperado: \${$totalEsperado}, recibido: \${$totalRecibido}). Recarga la página e intenta de nuevo."
            );
        }
    }

    private function prepareOrderData($data)
    {
        $deliveryRequested = !empty($data['deliveryRequested']) && $data['deliveryRequested'] !== '0';
        $subtotal = $this->calcularSubtotalCarrito($data['cartItems']);
        $costoEnvio = $deliveryRequested ? $this->configEnvio->calcularCostoEnvio($subtotal) : 0.0;
        $montoTotal = round($subtotal + $costoEnvio, 2);
        $metodoPago = ($data['paymentMethod'] ?? 'cash') === 'mercadopago' ? 'mercadopago' : 'cash';

        return [
            'nombre_cliente' => htmlspecialchars(trim($data['fullName']), ENT_QUOTES, 'UTF-8'),
            'telefono' => preg_replace('/\D+/', '', trim($data['phoneNumber'])),
            'direccion_texto' => $deliveryRequested ? htmlspecialchars(trim($data['addressText']), ENT_QUOTES, 'UTF-8') : null,
            'referencia' => $deliveryRequested && !empty($data['references'])
                ? htmlspecialchars(trim($data['references']), ENT_QUOTES, 'UTF-8') : null,
            'monto_total' => $montoTotal,
            'subtotal_productos' => $subtotal,
            'costo_envio_aplicado' => $costoEnvio,
            'estado_pago' => PedidoEstadoHelper::estadoPagoInicial($metodoPago),
            'estado_entrega' => 'PENDIENTE',
            'metodo_pago' => $metodoPago,
            'mercado_pago_pref_id' => $data['mercado_pago_pref_id'] ?? null,
            'mercado_pago_payment_id' => $data['mercado_pago_payment_id'] ?? null,
            'fecha_pedido' => $data['orderDate'] ?? date('Y-m-d H:i:s'),
            'envio_dom' => $deliveryRequested ? 1 : 0,
            'latitud' => $deliveryRequested ? (string)$data['latitude'] : null,
            'longitud' => $deliveryRequested ? (string)$data['longitude'] : null,
        ];
    }

    private function createOrder($pedidoData)
    {
        $idPedido = $this->pedidoModel->createPedido($pedidoData);
        if (!$idPedido) {
            throw new Exception('Error al crear el pedido en la base de datos');
        }
        return $idPedido;
    }

    private function addOrderItems($idPedido, $cartItemsJson)
    {
        $cartItems = json_decode($cartItemsJson, true);
        if (json_last_error() !== JSON_ERROR_NONE || !is_array($cartItems)) {
            throw new Exception('Error en el formato de los productos del carrito');
        }

        foreach ($cartItems as $item) {
            try {
                $titulo = $item['title'] ?? $item['name'] ?? $item['titulo'] ?? 'Producto sin nombre';
                $cantidad = (int)($item['quantity'] ?? $item['qty'] ?? $item['cantidad'] ?? 1);
                $precio = (float)($item['price'] ?? $item['precio'] ?? 0);
                $idProducto = isset($item['id']) ? (int)$item['id'] : null;

                if ($cantidad <= 0) {
                    $cantidad = 1;
                }
                if ($precio <= 0) {
                    continue;
                }

                if ($idProducto === null) {
                    $producto = $this->productoModel->getProductoByNombre($titulo);
                    $idProducto = $producto ? (int)$producto['id_producto'] : null;
                }

                $this->detallePedidoModel->createDetalle($idPedido, $idProducto, $titulo, $cantidad, $precio);
            } catch (Exception $e) {
                error_log('Error procesando item: ' . $e->getMessage());
            }
        }
    }

    private function createHistorialRecord($idPedido)
    {
        try {
            return $this->historialModel->create($idPedido);
        } catch (Exception $e) {
            error_log('Error al crear historial: ' . $e->getMessage());
            return false;
        }
    }

    public function updatePedidoMercadoPagoId($idPedido, $preferenceId)
    {
        return $this->pedidoModel->updatePedidoMercadoPagoId($idPedido, $preferenceId);
    }
}
