<?php
/**
 * Cart Model
 * Maps to `carts` and `cart_items` tables
 */

require_once __DIR__ . '/../Core/Model.php';

class Cart extends Model {
    protected string $table = 'carts';

    public function getOrCreateCart(int $userId): array {
        $sql = "SELECT * FROM `carts` WHERE user_id = :user_id LIMIT 1";
        $cart = $this->fetchOne($sql, [':user_id' => $userId]);

        if (!$cart) {
            $cartId = $this->insert([
                'user_id' => $userId,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ]);
            $cart = $this->findById($cartId);
        }

        return $cart;
    }

    public function getCartItemCount(int $userId): int {
        $sql = "SELECT SUM(ci.quantity) FROM `cart_items` ci
                JOIN `carts` c ON ci.cart_id = c.id
                JOIN `products` p ON ci.product_id = p.id
                WHERE c.user_id = :user_id AND p.status = 'active' AND p.deleted_at IS NULL";
        $stmt = $this->query($sql, [':user_id' => $userId]);
        $count = $stmt->fetchColumn();
        return $count ? (int)$count : 0;
    }

    public function getCartItemsGrouped(int $userId): array {
        $cart = $this->getOrCreateCart($userId);
        $cartId = (int)$cart['id'];

        $sql = "SELECT ci.id as cart_item_id, ci.quantity, ci.is_selected, ci.variation_summary, ci.sku_id,
                COALESCE(ci.unit_price, p.price) as price, p.price as base_price,
                p.id as product_id, p.name as product_name, p.slug as product_slug,
                p.original_price, p.stock, p.status as product_status,
                s.id as store_id, s.store_name, s.store_slug, s.status as store_status,
                s.commission_rate,
                (SELECT image_path FROM `product_images` pi WHERE pi.product_id = p.id ORDER BY pi.is_main DESC, pi.sort_order ASC LIMIT 1) as main_image
                FROM `cart_items` ci
                JOIN `products` p ON ci.product_id = p.id
                JOIN `stores` s ON p.store_id = s.id
                WHERE ci.cart_id = :cart_id AND p.deleted_at IS NULL
                ORDER BY s.store_name ASC, ci.created_at DESC";

        $items = $this->fetchAll($sql, [':cart_id' => $cartId]);

        // Group by store
        $stores = [];
        $grandTotal = 0;
        $selectedTotal = 0;
        $totalItems = 0;
        $selectedItemsCount = 0;

        foreach ($items as $item) {
            $storeId = (int)$item['store_id'];
            if (!isset($stores[$storeId])) {
                $stores[$storeId] = [
                    'store_id' => $storeId,
                    'store_name' => $item['store_name'],
                    'store_slug' => $item['store_slug'],
                    'store_status' => $item['store_status'],
                    'commission_rate' => $item['commission_rate'],
                    'items' => [],
                    'store_subtotal' => 0
                ];
            }

            $unitPrice = (float)$item['price'];
            $itemSubtotal = $unitPrice * (int)$item['quantity'];
            $item['subtotal'] = $itemSubtotal;
            $item['is_available'] = ($item['product_status'] === 'active' && $item['store_status'] === 'active' && (int)$item['stock'] > 0);

            $stores[$storeId]['items'][] = $item;
            $stores[$storeId]['store_subtotal'] += $itemSubtotal;

            $grandTotal += $itemSubtotal;
            $totalItems += (int)$item['quantity'];

            if ($item['is_selected'] && $item['is_available']) {
                $selectedTotal += $itemSubtotal;
                $selectedItemsCount += (int)$item['quantity'];
            }
        }

        return [
            'cart_id' => $cartId,
            'stores' => array_values($stores),
            'grand_total' => $grandTotal,
            'selected_total' => $selectedTotal,
            'total_items' => $totalItems,
            'selected_items_count' => $selectedItemsCount
        ];
    }

    public function addItem(int $cartId, int $productId, int $quantity = 1, ?string $variationSummary = null, ?float $unitPrice = null, ?int $skuId = null): bool {
        $variationSummary = !empty(trim($variationSummary ?? '')) ? trim($variationSummary) : null;

        if ($variationSummary !== null) {
            $sqlCheck = "SELECT id, quantity FROM `cart_items` 
                         WHERE cart_id = :cart_id AND product_id = :product_id AND variation_summary = :var LIMIT 1";
            $existing = $this->fetchOne($sqlCheck, [':cart_id' => $cartId, ':product_id' => $productId, ':var' => $variationSummary]);
        } else {
            $sqlCheck = "SELECT id, quantity FROM `cart_items` 
                         WHERE cart_id = :cart_id AND product_id = :product_id AND (variation_summary IS NULL OR variation_summary = '') LIMIT 1";
            $existing = $this->fetchOne($sqlCheck, [':cart_id' => $cartId, ':product_id' => $productId]);
        }

        if ($existing) {
            $newQty = (int)$existing['quantity'] + $quantity;
            $sqlUpdate = "UPDATE `cart_items` SET quantity = :qty, unit_price = :price, updated_at = NOW() WHERE id = :id";
            $this->query($sqlUpdate, [':qty' => $newQty, ':price' => $unitPrice, ':id' => $existing['id']]);
        } else {
            $sqlInsert = "INSERT INTO `cart_items` (`cart_id`, `product_id`, `variation_summary`, `sku_id`, `unit_price`, `quantity`, `is_selected`, `created_at`, `updated_at`) 
                          VALUES (:cart_id, :product_id, :var, :sku_id, :price, :qty, 1, NOW(), NOW())";
            $this->query($sqlInsert, [
                ':cart_id' => $cartId,
                ':product_id' => $productId,
                ':var' => $variationSummary,
                ':sku_id' => $skuId,
                ':price' => $unitPrice,
                ':qty' => $quantity
            ]);
        }

        return true;
    }

    public function updateQuantity(int $cartId, int $itemIdOrProductId, int $quantity): bool {
        if ($quantity <= 0) {
            return $this->removeItem($cartId, $itemIdOrProductId);
        }

        // Try updating by cart_items.id first
        $sql = "UPDATE `cart_items` SET quantity = :qty, updated_at = NOW() WHERE cart_id = :cart_id AND id = :id";
        $stmt = $this->query($sql, [':qty' => $quantity, ':cart_id' => $cartId, ':id' => $itemIdOrProductId]);
        if ($stmt->rowCount() > 0) {
            return true;
        }

        // Fallback updating by product_id
        $sql = "UPDATE `cart_items` SET quantity = :qty, updated_at = NOW() WHERE cart_id = :cart_id AND product_id = :pid";
        $this->query($sql, [':qty' => $quantity, ':cart_id' => $cartId, ':pid' => $itemIdOrProductId]);
        return true;
    }

    public function removeItem(int $cartId, int $itemIdOrProductId): bool {
        // Try deleting by cart_items.id first
        $sql = "DELETE FROM `cart_items` WHERE cart_id = :cart_id AND id = :id";
        $stmt = $this->query($sql, [':cart_id' => $cartId, ':id' => $itemIdOrProductId]);
        if ($stmt->rowCount() > 0) {
            return true;
        }

        // Fallback deleting by product_id
        $sql = "DELETE FROM `cart_items` WHERE cart_id = :cart_id AND product_id = :pid";
        $this->query($sql, [':cart_id' => $cartId, ':pid' => $itemIdOrProductId]);
        return true;
    }

    public function toggleSelect(int $cartId, int $itemIdOrProductId, bool $isSelected): bool {
        // Try updating by cart_items.id first
        $sql = "UPDATE `cart_items` SET is_selected = :sel, updated_at = NOW() WHERE cart_id = :cart_id AND id = :id";
        $stmt = $this->query($sql, [':sel' => $isSelected ? 1 : 0, ':cart_id' => $cartId, ':id' => $itemIdOrProductId]);
        if ($stmt->rowCount() > 0) {
            return true;
        }

        // Fallback updating by product_id
        $sql = "UPDATE `cart_items` SET is_selected = :sel, updated_at = NOW() WHERE cart_id = :cart_id AND product_id = :pid";
        $this->query($sql, [':sel' => $isSelected ? 1 : 0, ':cart_id' => $cartId, ':pid' => $itemIdOrProductId]);
        return true;
    }

    public function toggleSelectAll(int $cartId, bool $isSelected): bool {
        $sql = "UPDATE `cart_items` SET is_selected = :sel, updated_at = NOW() WHERE cart_id = :cart_id";
        $this->query($sql, [':sel' => $isSelected ? 1 : 0, ':cart_id' => $cartId]);
        return true;
    }

    public function clearSelected(int $cartId): void {
        $sql = "DELETE FROM `cart_items` WHERE cart_id = :cart_id AND is_selected = 1";
        $this->query($sql, [':cart_id' => $cartId]);
    }
}
