<?php

class OrderService
{
    public function calculateSubtotal($items)
    {
        $subtotal = 0;
        foreach ($items as $item) {
            $price = (float) ($item['price'] ?? 0);
            $quantity = (int) ($item['quantity'] ?? 1);
            $subtotal += $price * $quantity;

            if (!empty($item['addons']) && is_array($item['addons'])) {
                foreach ($item['addons'] as $addon) {
                    $addonPrice = (float) ($addon['price'] ?? 0);
                    $addonQty = (int) ($addon['quantity'] ?? 1);
                    $subtotal += $addonPrice * $addonQty * $quantity;
                }
            }
        }
        return round($subtotal, 2);
    }

    public function calculateTax($subtotal, $taxPercent)
    {
        return round($subtotal * ($taxPercent / 100), 2);
    }

    public function calculateServiceCharge($subtotal, $serviceChargePercent)
    {
        return round($subtotal * ($serviceChargePercent / 100), 2);
    }

    public function calculateDeliveryCharge($orderType, $deliveryCharge)
    {
        if ($orderType === 'delivery') {
            return (float) $deliveryCharge;
        }
        return 0;
    }

    public function calculateDiscount($subtotal, $offer)
    {
        if (!$offer) {
            return 0;
        }

        $discountType = $offer['discount_type'] ?? 'fixed';
        $discountValue = (float) ($offer['discount_value'] ?? 0);
        $minOrder = (float) ($offer['min_order'] ?? 0);

        if ($subtotal < $minOrder) {
            return 0;
        }

        if ($discountType === 'percentage') {
            $discount = $subtotal * ($discountValue / 100);
            $maxDiscount = (float) ($offer['max_discount'] ?? 0);
            if ($maxDiscount > 0 && $discount > $maxDiscount) {
                $discount = $maxDiscount;
            }
            return round($discount, 2);
        }

        return round(min($discountValue, $subtotal), 2);
    }

    public function calculateGrandTotal($subtotal, $tax, $serviceCharge, $deliveryCharge, $discount)
    {
        $total = $subtotal + $tax + $serviceCharge + $deliveryCharge - $discount;
        return round(max($total, 0), 2);
    }

    public function generateOrderNumber($restaurantId, $prefix = 'ORD')
    {
        $db = Database::getInstance();
        $datePrefix = $prefix . date('ymd');

        $stmt = $db->query(
            "SELECT order_number FROM orders WHERE restaurant_id = ? AND order_number LIKE ? ORDER BY id DESC LIMIT 1",
            [$restaurantId, $datePrefix . '%']
        );
        $lastOrder = $stmt->fetch();

        if ($lastOrder) {
            $lastNumber = (int) substr($lastOrder['order_number'], -4);
            $newNumber = str_pad($lastNumber + 1, 4, '0', STR_PAD_LEFT);
        } else {
            $newNumber = '0001';
        }

        return $datePrefix . $newNumber;
    }

    public function validateCart($cart, $restaurantId)
    {
        $errors = [];

        if (empty($cart['items']) || !is_array($cart['items'])) {
            $errors[] = 'Cart is empty.';
            return $errors;
        }

        $db = Database::getInstance();

        foreach ($cart['items'] as $index => $item) {
            $itemId = (int) ($item['id'] ?? 0);
            $quantity = (int) ($item['quantity'] ?? 0);

            if ($itemId <= 0) {
                $errors[] = 'Invalid item at position ' . ($index + 1) . '.';
                continue;
            }

            if ($quantity <= 0) {
                $errors[] = 'Invalid quantity for item #' . $itemId . '.';
                continue;
            }

            $stmt = $db->query(
                "SELECT id, regular_price, is_available FROM menu_items WHERE id = ? AND restaurant_id = ?",
                [$itemId, $restaurantId]
            );
            $menuItem = $stmt->fetch();

            if (!$menuItem) {
                $errors[] = 'Item #' . $itemId . ' not found.';
                continue;
            }

            if ((int) $menuItem['is_available'] !== 1) {
                $errors[] = 'Item #' . $itemId . ' is currently unavailable.';
            }

            if ((float) ($item['price'] ?? 0) !== (float) $menuItem['regular_price']) {
                $errors[] = 'Price mismatch for item #' . $itemId . '. Please refresh your cart.';
            }
        }

        return $errors;
    }

    public function recalculateOrder($cartData, $restaurantSettings)
    {
        $items = $cartData['items'] ?? [];
        $orderType = $cartData['order_type'] ?? 'dine_in';

        $subtotal = $this->calculateSubtotal($items);
        $taxPercent = (float) ($restaurantSettings['tax_percent'] ?? 0);
        $serviceChargePercent = (float) ($restaurantSettings['service_charge_percent'] ?? 0);
        $deliveryChargeAmount = (float) ($restaurantSettings['delivery_charge'] ?? 0);

        $tax = $this->calculateTax($subtotal, $taxPercent);
        $serviceCharge = $this->calculateServiceCharge($subtotal, $serviceChargePercent);
        $deliveryCharge = $this->calculateDeliveryCharge($orderType, $deliveryChargeAmount);
        $discount = 0;

        if (!empty($cartData['offer'])) {
            $discount = $this->calculateDiscount($subtotal, $cartData['offer']);
        }

        $grandTotal = $this->calculateGrandTotal($subtotal, $tax, $serviceCharge, $deliveryCharge, $discount);

        return [
            'subtotal'        => $subtotal,
            'tax'             => $tax,
            'tax_percent'     => $taxPercent,
            'service_charge'  => $serviceCharge,
            'service_charge_percent' => $serviceChargePercent,
            'delivery_charge' => $deliveryCharge,
            'discount'        => $discount,
            'grand_total'     => $grandTotal,
        ];
    }
}
