<?php
/**
 * OrderService
 * Handles Multi-Vendor Order creation, customer order history, and status tracking
 */

require_once __DIR__ . '/../Models/Order.php';
require_once __DIR__ . '/../Models/Cart.php';
require_once __DIR__ . '/../Models/UserAddress.php';
require_once __DIR__ . '/../Models/User.php';
require_once __DIR__ . '/../Models/ActivityLog.php';

class OrderService {
    private Order $orderModel;
    private Cart $cartModel;
    private UserAddress $addressModel;
    private User $userModel;
    private ActivityLog $activityLog;

    public function __construct() {
        $this->orderModel = new Order();
        $this->cartModel = new Cart();
        $this->addressModel = new UserAddress();
        $this->userModel = new User();
        $this->activityLog = new ActivityLog();
    }

    public function getCustomerOrders(int $customerId, ?string $status = null): array {
        return $this->orderModel->getCustomerOrders($customerId, $status);
    }

    public function getOrderDetail(string $orderNo, int $customerId): ?array {
        $order = $this->orderModel->findOrderByNo($orderNo, $customerId);
        if (!$order) {
            return null;
        }

        $order['items'] = $this->orderModel->getOrderItems((int)$order['id']);
        return $order;
    }

    /**
     * Place orders grouped by vendor store from selected cart items
     */
    public function placeOrder(int $customerId, int $addressId, string $paymentMethod = 'PromptPay', ?string $note = null): array {
        $user = $this->userModel->findById($customerId);
        $address = $this->addressModel->findUserAddress($addressId, $customerId);

        if (!$address) {
            return ['success' => false, 'message' => 'กรุณาเลือกที่อยู่ในการจัดส่งที่ถูกต้อง'];
        }

        $cartData = $this->cartModel->getCartItemsGrouped($customerId);
        if (empty($cartData['stores'])) {
            return ['success' => false, 'message' => 'ไม่มีสินค้าในรถเข็น'];
        }

        // Format delivery address text snapshot
        $deliveryAddressText = sprintf(
            "%s | โทร: %s\n%s %s %s %s\nตำบล/แขวง %s, อำเภอ/เขต %s, จังหวัด %s %s",
            $address['recipient_name'],
            $address['phone'],
            $address['house_number'],
            $address['village'] ? 'หมู่บ้าน ' . $address['village'] : '',
            $address['alley'] ? 'ซอย ' . $address['alley'] : '',
            $address['street'] ? 'ถนน ' . $address['street'] : '',
            $address['sub_district'],
            $address['district'],
            $address['province'],
            $address['postal_code']
        );

        $createdOrderNos = [];
        $cartId = (int)$cartData['cart_id'];

        foreach ($cartData['stores'] as $storeGroup) {
            // Filter only selected and available items in this store
            $selectedItems = array_filter($storeGroup['items'], fn($it) => $it['is_selected'] && $it['is_available']);
            if (empty($selectedItems)) {
                continue;
            }

            $storeSubtotal = 0;
            foreach ($selectedItems as $it) {
                $storeSubtotal += (float)$it['price'] * (int)$it['quantity'];
            }

            $shippingFee = 50.00; // Flat standard shipping per store order
            $discount = 0.00;
            $totalAmount = $storeSubtotal + $shippingFee - $discount;

            $commissionRate = (float)($storeGroup['commission_rate'] ?? 5.00);
            $commissionAmount = round(($storeSubtotal * ($commissionRate / 100.0)), 2);
            $netRevenue = $storeSubtotal - $commissionAmount;

            $orderNo = $this->orderModel->generateOrderNo();

            $orderId = $this->orderModel->createVendorOrder([
                'order_no' => $orderNo,
                'customer_id' => $customerId,
                'store_id' => (int)$storeGroup['store_id'],
                'shipping_address_id' => $addressId,
                'customer_name' => $address['recipient_name'],
                'customer_phone' => $address['phone'],
                'delivery_address' => $deliveryAddressText,
                'subtotal' => $storeSubtotal,
                'shipping_fee' => $shippingFee,
                'discount' => $discount,
                'total_amount' => $totalAmount,
                'commission_rate' => $commissionRate,
                'commission_amount' => $commissionAmount,
                'net_revenue' => $netRevenue,
                'order_status' => 'pending_payment',
                'payment_status' => 'pending',
                'payment_method' => $paymentMethod,
                'shipping_method' => 'Standard Delivery',
                'note' => $note,
                'payment_expires_at' => date('Y-m-d H:i:s', time() + 86400), // 24 hours
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ], $selectedItems);

            $createdOrderNos[] = $orderNo;
            $this->activityLog->record($customerId, 'order_placed', 'order', $orderId, "Placed order {$orderNo}");
        }

        if (empty($createdOrderNos)) {
            return ['success' => false, 'message' => 'กรุณาเลือกสินค้าอย่างน้อย 1 รายการเพื่อสั่งซื้อ'];
        }

        // Clear only selected items
        $this->cartModel->clearSelected($cartId);

        return [
            'success' => true,
            'message' => 'สั่งซื้อสินค้าเรียบร้อยแล้ว',
            'order_nos' => $createdOrderNos,
            'primary_order_no' => $createdOrderNos[0]
        ];
    }

    /**
     * Cancel an Order by Customer
     * Handles stock restoration, payment status update, and refund integration
     */
    public function cancelOrder(string $orderNo, int $customerId, string $reason): array {
        $reason = trim($reason);
        if (empty($reason)) {
            return ['success' => false, 'message' => 'กรุณาระบุเหตุผลในการยกเลิกคำสั่งซื้อ'];
        }

        return DB::transaction(function($pdo) use ($orderNo, $customerId, $reason) {
            // 1. Lock and retrieve order
            $stmt = $pdo->prepare("SELECT * FROM `orders` WHERE `order_no` = :no AND `customer_id` = :cid AND `deleted_at` IS NULL FOR UPDATE");
            $stmt->execute([':no' => $orderNo, ':cid' => $customerId]);
            $order = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$order) {
                return ['success' => false, 'message' => 'ไม่พบคำสั่งซื้อนี้ หรือคุณไม่มีสิทธิ์ยกเลิก'];
            }

            $orderId = (int)$order['id'];
            $currentStatus = $order['order_status'];

            // 2. Validate Cancellable Status
            $cancellableStatuses = ['pending_payment', 'awaiting_verification', 'payment_confirmed', 'preparing'];
            if (!in_array($currentStatus, $cancellableStatuses, true)) {
                if ($currentStatus === 'cancelled') {
                    return ['success' => false, 'message' => 'คำสั่งซื้อนี้ถูกยกเลิกไปแล้ว'];
                }
                return ['success' => false, 'message' => 'ไม่สามารถยกเลิกคำสั่งซื้อในสถานะนี้ได้ (คำสั่งซื้ออยู่ระหว่างจัดส่งหรือดำเนินการเสร็จสิ้นแล้ว)'];
            }

            // 3. Restore Stock for each order item
            $itemsStmt = $pdo->prepare("SELECT * FROM `order_items` WHERE `order_id` = :oid");
            $itemsStmt->execute([':oid' => $orderId]);
            $items = $itemsStmt->fetchAll(PDO::FETCH_ASSOC);

            $stmtProdStock = $pdo->prepare("UPDATE `products` SET `stock` = `stock` + :qty WHERE `id` = :pid");
            $stmtSkuStock = $pdo->prepare("UPDATE `product_skus` SET `stock` = `stock` + :qty WHERE `id` = :skuid");

            foreach ($items as $item) {
                $qty = (int)$item['quantity'];
                $stmtProdStock->execute([':qty' => $qty, ':pid' => (int)$item['product_id']]);
                if (!empty($item['sku_id'])) {
                    $stmtSkuStock->execute([':qty' => $qty, ':skuid' => (int)$item['sku_id']]);
                }
            }

            // 4. Payment & Refund Integration
            $payStmt = $pdo->prepare("SELECT * FROM `payments` WHERE `order_id` = :oid LIMIT 1 FOR UPDATE");
            $payStmt->execute([':oid' => $orderId]);
            $payment = $payStmt->fetch(PDO::FETCH_ASSOC);

            $cancelNoteText = ($order['note'] ? $order['note'] . "\n" : "") . "[ยกเลิกคำสั่งซื้อเมื่อ " . date('d/m/Y H:i') . "]: " . $reason;
            $newPaymentStatus = 'cancelled';
            $newOrderStatus = 'cancelled';
            $isPaid = false;

            if ($payment) {
                $paymentId = (int)$payment['id'];
                $isPaid = in_array($payment['payment_status'], ['confirmed', 'paid'], true) 
                          || in_array($currentStatus, ['payment_confirmed', 'preparing'], true);

                if ($isPaid) {
                    $newPaymentStatus = 'refund_pending';
                    $newOrderStatus = 'cancelled';

                    // Insert into refunds table
                    $pdo->prepare("INSERT INTO `refunds` (`order_id`, `customer_id`, `store_id`, `amount`, `reason`, `status`, `created_at`, `updated_at`)
                                   VALUES (:oid, :cid, :sid, :amt, :reason, 'pending', NOW(), NOW())")
                        ->execute([
                            ':oid' => $orderId,
                            ':cid' => $customerId,
                            ':sid' => (int)$order['store_id'],
                            ':amt' => (float)$order['total_amount'],
                            ':reason' => "ลูกค้ายกเลิกคำสั่งซื้อที่ชำระเงินแล้ว: " . $reason
                        ]);

                    // Update payment status
                    $pdo->prepare("UPDATE `payments` SET `payment_status` = 'refund_pending', `cancelled_at` = NOW(), `note` = :note, `updated_at` = NOW() WHERE `id` = :pid")
                        ->execute([':note' => $reason, ':pid' => $paymentId]);
                } else {
                    $newPaymentStatus = 'cancelled';
                    $newOrderStatus = 'cancelled';
                    $pdo->prepare("UPDATE `payments` SET `payment_status` = 'cancelled', `cancelled_at` = NOW(), `note` = :note, `updated_at` = NOW() WHERE `id` = :pid")
                        ->execute([':note' => $reason, ':pid' => $paymentId]);
                }
            }

            // 5. Update Order Status
            $pdo->prepare("UPDATE `orders` SET `order_status` = :ostatus, `payment_status` = :pstatus, `note` = :note, `updated_at` = NOW() WHERE `id` = :oid")
                ->execute([
                    ':ostatus' => $newOrderStatus,
                    ':pstatus' => $newPaymentStatus,
                    ':note'    => $cancelNoteText,
                    ':oid'     => $orderId
                ]);

            // 6. Record Activity Log
            $this->activityLog->record($customerId, 'order_cancelled', 'order', $orderId, "Customer cancelled order #{$orderNo}. Reason: {$reason}");

            // 7. Dispatch Notifications
            require_once __DIR__ . '/NotificationService.php';
            $notifService = new NotificationService();
            $notifService->onOrderCancelled($orderId, $orderNo, $reason, $customerId, (int)$order['store_id']);

            return [
                'success' => true,
                'message' => 'ยกเลิกคำสั่งซื้อเรียบร้อยแล้ว' . ($isPaid ? ' (ระบบได้ส่งคำขอคืนเงินเรียบร้อยแล้ว)' : '')
            ];
        });
    }
}
