<?php

class OrderController {

    // ─── CHECKOUT ─────────────────────────────────────
    public static function checkout(): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $body   = getJsonBody();

        $name        = trim($body['name'] ?? '');
        $phone       = trim($body['phone'] ?? '');
        $address     = trim($body['address'] ?? '');
        $city        = trim($body['city'] ?? '');
        $state       = trim($body['state'] ?? '');
        $pincode     = trim($body['pincode'] ?? '');
        $startDate   = trim($body['start_date'] ?? date('Y-m-d'));
        $rentalDays  = max(0, (int)($body['rental_days'] ?? 3));
        $isPurchase  = ($rentalDays === 0);
        $instructions = trim($body['special_instructions'] ?? '');
        $paymentMethod = trim($body['payment_method'] ?? 'cod');
        $appTotal    = $body['total_amount'] ?? null;

        // ✅ Validation
        $errors = [];
        if (!$name)    $errors['name'] = 'Name required';
        if (!$phone)   $errors['phone'] = 'Phone required';
        if (!$address) $errors['address'] = 'Address required';
        if (!$city)    $errors['city'] = 'City required';
        if (!$pincode) $errors['pincode'] = 'Pincode required';
        if ($errors) sendError('Validation failed', 422, $errors);

        $db = getDb();

        // ✅ Fetch cart
        $stmt = $db->prepare("
            SELECT ci.product_id, ci.quantity,
                   p.price, p.discount_percent, p.stock, p.name, p.security_deposit
            FROM cart_items ci
            JOIN products p ON p.id = ci.product_id
            WHERE ci.user_id = ?
        ");
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $items = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();

        if (empty($items)) sendError('Cart is empty', 400);

        // ✅ Calculate total
        $total = 0;
        $returnDate = date('Y-m-d', strtotime("$startDate +$rentalDays days"));

        foreach ($items as $item) {
            if ($item['stock'] < $item['quantity']) {
                sendError("Out of stock: {$item['name']}", 409);
            }

            $price = ProductController::effectivePrice(
                (float)$item['price'],
                (int)$item['discount_percent']
            );

            // Rental cost: (Price * Qty * Days) + (Security Deposit * Qty)
            $itemRentalCost = $price * $item['quantity'] * $rentalDays;
            $itemsDeposit = (float)$item['security_deposit'] * $item['quantity'];
            
            $total += $itemRentalCost + $itemsDeposit;
        }

        // Use total from app if available
        if ($appTotal !== null) {
            $total = (float)$appTotal;
        }

        $shipping = "$name, $phone, $address, $city, $state - $pincode";

        // ─── Razorpay: Create payment order only (no DB record until payment verified) ───
        if ($paymentMethod === 'razorpay' || $paymentMethod === 'upi') {

            $amount = (int) round($total * 100);

            $ch = curl_init('https://api.razorpay.com/v1/orders');
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_POST => true,
                CURLOPT_USERPWD => RAZORPAY_KEY_ID . ':' . RAZORPAY_KEY_SECRET,
                CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
                CURLOPT_POSTFIELDS => json_encode([
                    'amount' => $amount,
                    'currency' => 'INR',
                    'receipt' => 'cart_' . $userId . '_' . time()
                ])
            ]);

            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            if ($httpCode !== 200) {
                sendError('Razorpay order creation failed', 500);
            }

            $razorpayOrder = json_decode($response, true);

            sendSuccess([
                'razorpay_order' => $razorpayOrder,
                'total' => round($total, 2),
                'checkout_data' => [
                    'type' => 'cart',
                    'shipping' => $shipping,
                    'instructions' => $instructions,
                    'start_date' => $startDate,
                    'return_date' => $returnDate,
                    'rental_days' => $rentalDays,
                    'total' => round($total, 2),
                    'payment_method' => $paymentMethod,
                ]
            ], 'Checkout initiated', 201);

        } else {
            // ─── COD: Create order immediately ────────────────────
            $stmt = $db->prepare("
                INSERT INTO orders 
                (user_id, total_price, status, shipping_address,
                 special_instructions, start_date, return_date, rental_days,
                 payment_status, created_at)
                VALUES (?, ?, 'Pending', ?, ?, ?, ?, ?, 'Pending', NOW())
            ");
            $stmt->bind_param(
                'idssssi',
                $userId,
                $total,
                $shipping,
                $instructions,
                $startDate,
                $returnDate,
                $rentalDays
            );
            $stmt->execute();
            $orderId = $stmt->insert_id;
            $stmt->close();

            // Insert order items
            $stmtItem = $db->prepare("
                INSERT INTO order_items (order_id, product_id, product_name, quantity, price, security_deposit)
                VALUES (?, ?, ?, ?, ?, ?)
            ");

            foreach ($items as $item) {
                $price = ProductController::effectivePrice(
                    (float)$item['price'],
                    (int)$item['discount_percent']
                );

                $stmtItem->bind_param(
                    'iisidd',
                    $orderId,
                    $item['product_id'],
                    $item['name'],
                    $item['quantity'],
                    $price,
                    $item['security_deposit']
                );
                $stmtItem->execute();
            }

            $stmtItem->close();

            // COD
            $stmt = $db->prepare("
                UPDATE orders 
                SET payment_status = 'COD', payment_method = ?, status='Confirmed'
                WHERE id = ?
            ");
            $stmt->bind_param('si', $paymentMethod, $orderId);
            $stmt->execute();
            $stmt->close();

            // ✅ For COD → reduce stock + clear cart immediately
            self::finalizeOrder($db, $userId, $orderId);

            sendSuccess([
                'order_id' => $orderId,
                'total' => round($total, 2),
            ], 'Checkout successful', 201);
        }
    }

    // ─── BUY NOW (Direct Purchase) ─────────────────────
    public static function buyNowCheckout(): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $body   = getJsonBody();

        $productId     = (int)($body['product_id'] ?? 0);
        $quantity      = max(1, (int)($body['quantity'] ?? 1));
        $paymentMethod = trim($body['payment_method'] ?? 'razorpay');

        if (!$productId) sendError('Product ID required', 422);

        $db = getDb();

        // 1. Fetch Product
        $stmt = $db->prepare("SELECT id, name, price, original_price, market_price, discount_percent, stock FROM products WHERE id = ? LIMIT 1");
        $stmt->bind_param('i', $productId);
        $stmt->execute();
        $product = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$product) sendError('Product not found', 404);
        if ($product['stock'] < $quantity) sendError('Insufficient stock', 409);

        // 2. Get User Address (Try default first, then fallback to any)
        $stmt = $db->prepare("SELECT address, full_name, phone, city, state, pincode FROM addresses WHERE user_id = ? ORDER BY is_default DESC LIMIT 1");
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $addressRow = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$addressRow) sendError('No default address found. Please add an address in your profile.', 404);

        $shipping = "{$addressRow['full_name']}, {$addressRow['phone']}, {$addressRow['address']}, {$addressRow['city']}, {$addressRow['state']} - {$addressRow['pincode']}";

        // 3. Calculate Total (Standard E-commerce)
        // Order of priority: market_price > original_price > discounted rent price (fallback only)
        $marketPrice   = (float)($product['market_price'] ?? 0);
        $originalPrice = (float)($product['original_price'] ?? 0);
        $rentPrice     = (float)($product['price'] ?? 0);

        if ($marketPrice > 0) {
            $price = $marketPrice;
        } elseif ($originalPrice > 0) {
            $price = $originalPrice;
        } else {
            $price = $rentPrice; // Absolute fallback
        }

        $total = $price * $quantity;
        if (isset($body['total_amount']) && floatval($body['total_amount']) > 0) {
            $total = floatval($body['total_amount']);
        }

        // 4. Create Razorpay order only (order saved after payment verification)
        $razorpayOrder = null;
        if ($paymentMethod === 'razorpay') {
            $amount = (int) round($total * 100);

            $ch = curl_init('https://api.razorpay.com/v1/orders');
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_POST => true,
                CURLOPT_USERPWD => RAZORPAY_KEY_ID . ':' . RAZORPAY_KEY_SECRET,
                CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
                CURLOPT_POSTFIELDS => json_encode([
                    'amount' => $amount,
                    'currency' => 'INR',
                    'receipt' => 'buynow_' . $userId . '_' . time()
                ])
            ]);

            $response = curl_exec($ch);
            curl_close($ch);

            $razorpayOrder = json_decode($response, true);
        }

        sendSuccess([
            'razorpay_order' => $razorpayOrder,
            'total' => round($total, 2),
            'checkout_data' => [
                'type' => 'buy_now',
                'product_id' => $productId,
                'quantity' => $quantity,
                'shipping' => $shipping,
                'total' => round($total, 2),
                'payment_method' => 'razorpay',
            ]
        ], 'Buy Now order initiated', 201);
    }

    // ─── VERIFY PAYMENT (Creates order only after successful payment) ─────────
    public static function verifyPayment(): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $body   = getJsonBody();

        $paymentId       = trim($body['razorpay_payment_id'] ?? '');
        $razorpayOrderId = trim($body['razorpay_order_id'] ?? '');
        $signature       = trim($body['razorpay_signature'] ?? '');
        $checkoutData    = $body['checkout_data'] ?? null;

        if (!$paymentId || !$razorpayOrderId || !$signature || !$checkoutData) {
            sendError('Missing payment or checkout data', 422);
        }

        // Verify Razorpay signature
        $generated = hash_hmac(
            'sha256',
            "$razorpayOrderId|$paymentId",
            RAZORPAY_KEY_SECRET
        );

        if (!hash_equals($generated, $signature)) {
            sendError('Invalid signature', 400);
        }

        $db = getDb();
        $type = $checkoutData['type'] ?? '';
        $orderId = 0;

        if ($type === 'cart') {
            // ─── Cart Checkout (Rental or Purchase) ───────────────
            $shipping     = $checkoutData['shipping'] ?? '';
            $instructions = $checkoutData['instructions'] ?? '';
            $startDate    = $checkoutData['start_date'] ?? date('Y-m-d');
            $returnDate   = $checkoutData['return_date'] ?? date('Y-m-d', strtotime('+3 days'));
            $rentalDays   = (int)($checkoutData['rental_days'] ?? 3);
            $total        = (float)($checkoutData['total'] ?? 0);
            $paymentMethod = $checkoutData['payment_method'] ?? 'razorpay';

            // Fetch current cart items
            $stmt = $db->prepare("
                SELECT ci.product_id, ci.quantity,
                       p.price, p.discount_percent, p.stock, p.name, p.security_deposit
                FROM cart_items ci
                JOIN products p ON p.id = ci.product_id
                WHERE ci.user_id = ?
            ");
            $stmt->bind_param('i', $userId);
            $stmt->execute();
            $items = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
            $stmt->close();

            if (empty($items)) sendError('Cart is empty', 400);

            // Create order (only now, after payment is verified)
            $stmt = $db->prepare("
                INSERT INTO orders 
                (user_id, total_price, status, shipping_address,
                 special_instructions, start_date, return_date, rental_days,
                 payment_status, payment_method, payment_id, razorpay_order_id, created_at)
                VALUES (?, ?, 'Pending', ?, ?, ?, ?, ?, 'Paid', ?, ?, ?, NOW())
            ");
            $stmt->bind_param(
                'idssssisss',
                $userId, $total, $shipping, $instructions,
                $startDate, $returnDate, $rentalDays,
                $paymentMethod, $paymentId, $razorpayOrderId
            );
            $stmt->execute();
            $orderId = $stmt->insert_id;
            $stmt->close();

            // Insert order items
            $stmtItem = $db->prepare("
                INSERT INTO order_items (order_id, product_id, product_name, quantity, price, security_deposit)
                VALUES (?, ?, ?, ?, ?, ?)
            ");

            foreach ($items as $item) {
                $price = ProductController::effectivePrice(
                    (float)$item['price'],
                    (int)$item['discount_percent']
                );

                $stmtItem->bind_param(
                    'iisidd',
                    $orderId,
                    $item['product_id'],
                    $item['name'],
                    $item['quantity'],
                    $price,
                    $item['security_deposit']
                );
                $stmtItem->execute();
            }

            $stmtItem->close();

            // Finalize: reduce stock + clear cart if rental
            $shouldClearCart = ($rentalDays > 0);
            self::finalizeOrder($db, $userId, $orderId, $shouldClearCart);

        } elseif ($type === 'buy_now') {
            // ─── Buy Now (Direct Purchase) ────────────────────────
            $productId = (int)($checkoutData['product_id'] ?? 0);
            $quantity  = max(1, (int)($checkoutData['quantity'] ?? 1));
            $total     = (float)($checkoutData['total'] ?? 0);
            $shipping  = $checkoutData['shipping'] ?? '';

            // Fetch product
            $stmt = $db->prepare("SELECT id, name, price, original_price, market_price, discount_percent, stock FROM products WHERE id = ? LIMIT 1");
            $stmt->bind_param('i', $productId);
            $stmt->execute();
            $product = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            if (!$product) sendError('Product not found', 404);
            if ($product['stock'] < $quantity) sendError('Insufficient stock', 409);

            $marketPrice   = (float)($product['market_price'] ?? 0);
            $originalPrice = (float)($product['original_price'] ?? 0);
            $rentPrice     = (float)($product['price'] ?? 0);
            $price = $marketPrice > 0 ? $marketPrice : ($originalPrice > 0 ? $originalPrice : $rentPrice);

            // Create order (rental_days = 0, only after payment verified)
            $paymentMethod = 'razorpay';
            $stmt = $db->prepare("
                INSERT INTO orders 
                (user_id, total_price, status, shipping_address,
                 payment_status, rental_days, start_date, return_date,
                 payment_method, payment_id, razorpay_order_id, created_at)
                VALUES (?, ?, 'Pending', ?, 'Paid', 0, NOW(), NOW(), ?, ?, ?, NOW())
            ");
            $stmt->bind_param('idssss', $userId, $total, $shipping, $paymentMethod, $paymentId, $razorpayOrderId);
            $stmt->execute();
            $orderId = $stmt->insert_id;
            $stmt->close();

            // Insert order item
            $stmt = $db->prepare("
                INSERT INTO order_items (order_id, product_id, product_name, quantity, price, security_deposit)
                VALUES (?, ?, ?, ?, ?, 0)
            ");
            $stmt->bind_param('iisid', $orderId, $productId, $product['name'], $quantity, $price);
            $stmt->execute();
            $stmt->close();

            // Finalize: reduce stock, don't clear cart
            self::finalizeOrder($db, $userId, $orderId, false);

        } else {
            sendError('Invalid checkout type', 422);
        }

        sendSuccess(['order_id' => $orderId], 'Payment verified and order created');
    }

    // ─── FINAL STEP (COMMON) ────────────────────────────
    private static function finalizeOrder($db, $userId, $orderId, $clearCart = true): void {

        // Reduce stock
        $stmt = $db->prepare("
            UPDATE products p
            JOIN order_items oi ON p.id = oi.product_id
            SET p.stock = p.stock - oi.quantity
            WHERE oi.order_id = ?
        ");
        $stmt->bind_param('i', $orderId);
        $stmt->execute();
        $stmt->close();

        if ($clearCart) {
            // Clear cart
            $stmt = $db->prepare("DELETE FROM cart_items WHERE user_id = ?");
            $stmt->bind_param('i', $userId);
            $stmt->execute();
            $stmt->close();
        }
    }



    // ─── GET /api/orders ──────────────────────────────────────────────────────
    public static function listOrders(): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $db     = getDb();

        $stmt = $db->prepare(
            "SELECT id, total_price, status, payment_status, rental_days,
                    start_date, return_date, created_at
             FROM orders WHERE user_id = ? ORDER BY created_at DESC"
        );
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $orders = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();

        sendSuccess($orders);
    }

    // ─── GET /api/orders/{id} ─────────────────────────────────────────────────
    public static function orderById(string $id): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $db     = getDb();

        $stmt = $db->prepare(
            "SELECT id, total_price, shipping_address, special_instructions,
                    status, payment_status, rental_days, start_date, return_date, created_at
             FROM orders WHERE id = ? AND user_id = ? LIMIT 1"
        );
        $stmt->bind_param('ii', $id, $userId);
        $stmt->execute();
        $order = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$order) sendError('Order not found', 404);

        // Load order items with product image
        $stmt = $db->prepare(
            "SELECT oi.product_id, oi.product_name, oi.quantity, oi.price,
                    p.images
             FROM order_items oi
             LEFT JOIN products p ON p.id = oi.product_id
             WHERE oi.order_id = ?"
        );
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $order['items'] = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();

        sendSuccess($order);
    }

    // ─── POST /api/orders/update-status ───────────────────────────────────────
    public static function updateStatus(): void {
        // In a real app, you would verify if the user has an ADMIN role here.
        // For now, since there's no admin role in the users table, we'll implement the logic.
        $body = getJsonBody();
        $orderId = (int)($body['order_id'] ?? 0);
        $status  = trim($body['status'] ?? '');

        if (!$orderId || !$status) {
            sendError('Order ID and status are required', 422);
        }

        $db = getDb();
        $stmt = $db->prepare("UPDATE orders SET status = ? WHERE id = ?");
        $stmt->bind_param('si', $status, $orderId);
        
        if ($stmt->execute()) {
            $stmt->close();
            sendSuccess(['order_id' => $orderId, 'status' => $status], 'Order status updated successfully');
        } else {
            $stmt->close();
            sendError('Failed to update order status', 500);
        }
    }

    // ─── POST /api/orders/return ─────────────────────────────────────────────
    public static function requestReturn(): void {
        $user   = AuthController::requireAuth();
        $userId = $user['id'];
        $db     = getDb();

        // Support both multipart form-data (with image) and JSON (no image)
        $orderId = (int)($_POST['order_id'] ?? 0);
        $reason  = trim($_POST['reason'] ?? '');

        // Fallback to JSON body if POST fields are empty
        if (!$orderId) {
            $body    = getJsonBody();
            $orderId = (int)($body['order_id'] ?? 0);
            $reason  = trim($body['reason'] ?? 'Not specified');
        }

        if (!$reason) $reason = 'Not specified';

        if (!$orderId) {
            sendError('Order ID is required', 422);
        }

        // Verify order belongs to user and is a purchase (rental_days == 0)
        $stmt = $db->prepare("SELECT id, status, rental_days FROM orders WHERE id = ? AND user_id = ?");
        $stmt->bind_param('ii', $orderId, $userId);
        $stmt->execute();
        $order = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$order) {
            sendError('Order not found', 404);
        }

        if ((int)$order['rental_days'] > 0) {
            sendError('Please use the rental pickup flow for returns', 400);
        }

        if ($order['status'] !== 'Delivered') {
            sendError('Returns can only be requested for delivered orders', 400);
        }

        // ─── Handle Damage Image Upload ──────────────────────────────
        $returnImagePath = null;

        if (isset($_FILES['damage_image']) && $_FILES['damage_image']['error'] === UPLOAD_ERR_OK) {
            $file    = $_FILES['damage_image'];
            $ext     = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
            $allowed = ['jpg', 'jpeg', 'png', 'webp', 'gif'];

            if (!in_array($ext, $allowed)) {
                sendError('Invalid image type. Allowed: jpg, png, webp', 422);
            }

            if ($file['size'] > 5 * 1024 * 1024) {
                sendError('Image too large. Maximum size is 5 MB', 422);
            }

            $uploadDir = __DIR__ . '/../../assets/productimage/';
            if (!is_dir($uploadDir)) {
                mkdir($uploadDir, 0775, true);
            }

            $filename    = 'return_' . $orderId . '_' . time() . '.' . $ext;
            $destination = $uploadDir . $filename;

            if (!move_uploaded_file($file['tmp_name'], $destination)) {
                sendError('Failed to save image. Please try again.', 500);
            }

            $returnImagePath = 'assets/productimage/' . $filename;
        }

        // ─── Update Order ────────────────────────────────────────────
        $newStatus = 'Return Requested';
        $notes     = "User requested return. Reason: " . $reason;

        if ($returnImagePath !== null) {
            $stmt = $db->prepare("UPDATE orders SET status = ?, return_image = ?, special_instructions = CONCAT(IFNULL(special_instructions, ''), '\nReturn Request: ', ?) WHERE id = ?");
            $stmt->bind_param('sssi', $newStatus, $returnImagePath, $reason, $orderId);
        } else {
            $stmt = $db->prepare("UPDATE orders SET status = ?, special_instructions = CONCAT(IFNULL(special_instructions, ''), '\nReturn Request: ', ?) WHERE id = ?");
            $stmt->bind_param('ssi', $newStatus, $reason, $orderId);
        }

        if ($stmt->execute()) {
            $stmt->close();

            // Add to history
            $historyNote = $notes . ($returnImagePath ? ' [Damage image attached]' : '');
            $stmt = $db->prepare("INSERT INTO order_history (order_id, status, notes, updated_by) VALUES (?, ?, ?, 'user')");
            $stmt->bind_param('iss', $orderId, $newStatus, $historyNote);
            $stmt->execute();
            $stmt->close();

            // Notify Admin
            $notifTitle = "Purchase Return Requested - Order #$orderId";
            $notifMsg   = "User requested return for order #$orderId. Reason: $reason" . ($returnImagePath ? ' (damage image attached)' : '');
            $db->query("INSERT INTO admin_notifications (title, message, type) VALUES ('$notifTitle', '$notifMsg', 'return')");

            sendSuccess(
                ['return_image' => $returnImagePath],
                'Return request submitted successfully'
            );
        } else {
            $stmt->close();
            sendError('Failed to submit return request', 500);
        }
    }
}