<?php

namespace App\Http\Controllers;

use App\Models\CartItem;
use App\Models\Category;
use App\ProductRepositoryInterface;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ProductController extends Controller
{
    public function __construct(
        protected ProductRepositoryInterface $productRepository
    ) {
    }

    /**
     * Get categories with subcategories and product counts
     */
    protected function getCategoriesWithCounts($searchQuery = '', $selectedCategoryIds = [], bool $onlyStockout = false)
    {
        $rootCategories = Category::active()
            ->root()
            ->orderBy('sort_order')
            ->with(['children' => function ($query) {
                $query->active()->orderBy('sort_order');
            }])
            ->get();

        // Calculate product counts for each category
        foreach ($rootCategories as $category) {
            // Get all category IDs including subcategories
            $categoryIds = [$category->id];
            foreach ($category->children as $child) {
                $categoryIds[] = $child->id;
            }

            // Count products using repository
            $filters = ['category_ids' => $categoryIds];
            if ($onlyStockout) {
                $filters['only_stockout'] = true;
            } elseif (trim((string) ($searchQuery ?? '')) !== '') {
                $filters['include_out_of_stock'] = true;
            }

            $category->product_count = $this->productRepository->search($searchQuery ?? '', $filters)->total();

            // Count products for each subcategory
            foreach ($category->children as $child) {
                $childFilters = ['category_ids' => [$child->id]];
                if ($onlyStockout) {
                    $childFilters['only_stockout'] = true;
                } elseif (trim((string) ($searchQuery ?? '')) !== '') {
                    $childFilters['include_out_of_stock'] = true;
                }
                $child->product_count = $this->productRepository->search($searchQuery ?? '', $childFilters)->total();
            }
        }

        return $rootCategories;
    }

    public function show(string $slug, Request $request): View|RedirectResponse
    {
        $resolved = $this->productRepository->findActiveBySlug($slug);

        if (!$resolved) {
            abort(404);
        }

        $initialVariantId = 0;

        // Slug points to a variant: redirect to canonical URL (parent slug + ?variant=id)
        if ($resolved->parent_id) {
            $parent = $resolved->parent;
            return redirect()->route('product.show', [
                'slug' => $parent->slug,
                'variant' => $resolved->id,
            ], 301);
        }

        // Resolved product is parent or single: use cache for display product
        $product = \Illuminate\Support\Facades\Cache::remember('product_detail_' . $slug, 600, function () use ($resolved) {
            $resolved->load(['category', 'unit', 'media']);
            return $resolved;
        });

        // Load variants for variant parent products (not cached as they change frequently)
        if (is_null($product->parent_id) && $product->product_type === 'variant') {
            $product->load('variants.attributeValues.attribute');
            $requestedVariantId = (int) $request->query('variant');
            $activeVariants = $product->variants->where('is_active', true);
            $variantIds = $activeVariants->pluck('id')->toArray();
            
            if ($requestedVariantId && in_array($requestedVariantId, $variantIds, true)) {
                // Requested variant is valid
                $initialVariantId = $requestedVariantId;
            } elseif ($activeVariants->isNotEmpty()) {
                // Requested variant is invalid or not provided: select first available variant
                $initialVariantId = $activeVariants->first()->id;
            } else {
                // No active variants available
                $initialVariantId = 0;
            }
        }

        // Load paginated reviews (don't cache paginated results as they change with page)
        $reviews = $product->approvedReviews()
            ->with('user:id,name')
            ->latest()
            ->paginate(10);

        // Cache related products; if empty, show recent products so the section is never empty
        $relatedCacheKey = 'product_related_' . $product->id;
        $relatedProducts = \Illuminate\Support\Facades\Cache::remember($relatedCacheKey, 600, function () use ($product) {
            return $this->productRepository->getRelated($product->id, $product->category_id, 4);
        });

        if ($relatedProducts->isEmpty()) {
            $relatedProducts = \Illuminate\Support\Facades\Cache::remember('product_recent_' . $product->id, 600, function () use ($product) {
                return $this->productRepository->getRecent($product->id, 4);
            });
            $relatedSectionTitle = 'Recent Products';
            $relatedSectionSubtitle = "Check out what's new";
        } else {
            $relatedSectionTitle = 'Related Products';
            $relatedSectionSubtitle = 'You might also like';
        }

        // Get cart quantities
        $cart = $this->getCart($request);
        $cartQuantity = 0;
        $variantCartQuantities = [];

        if (is_null($product->parent_id) && $product->product_type === 'variant') {
            // For variant products: get cart quantities for all active variants
            $activeVariantIds = $product->variants->where('is_active', true)->pluck('id')->toArray();
            if (!empty($activeVariantIds)) {
                $cartItems = CartItem::where('cart_id', $cart->id)
                    ->whereIn('product_id', $activeVariantIds)
                    ->get();
                
                foreach ($cartItems as $item) {
                    $variantCartQuantities[$item->product_id] = $item->qty;
                }
            }
            
            // Set cart quantity for initial variant if selected
            if ($initialVariantId > 0 && isset($variantCartQuantities[$initialVariantId])) {
                $cartQuantity = $variantCartQuantities[$initialVariantId];
            }
        } else {
            // For single products: get cart quantity for this product
            $cartItem = CartItem::where('cart_id', $cart->id)
                ->where('product_id', $product->id)
                ->first();
            
            if ($cartItem) {
                $cartQuantity = $cartItem->qty;
            }
        }

        return view('product.show', compact('product', 'relatedProducts', 'reviews', 'initialVariantId', 'relatedSectionTitle', 'relatedSectionSubtitle', 'cartQuantity', 'variantCartQuantities'));
    }

    /**
     * Display new arrivals page
     */
    public function newArrivals(Request $request): View
    {
        // Handle multiple category filtering from checkboxes
        $selectedCategoryIds = $request->has('categories') && is_array($request->categories) 
            ? $request->categories 
            : [];

        $allCategoryIds = [];
        if (!empty($selectedCategoryIds)) {
            // Include subcategories when parent is selected
            foreach ($selectedCategoryIds as $catId) {
                $category = Category::find($catId);
                if ($category) {
                    $allCategoryIds[] = $category->id;
                    // Add subcategories
                    $subcategories = Category::where('parent_id', $category->id)->active()->pluck('id');
                    $allCategoryIds = array_merge($allCategoryIds, $subcategories->toArray());
                }
            }
            $allCategoryIds = array_unique($allCategoryIds);
        }

        $onlyStockout = $request->boolean('only_stockout');

        // Use repository for search
        $filters = ['per_page' => 20];
        if (!empty($allCategoryIds)) {
            $filters['category_ids'] = $allCategoryIds;
        }
        if ($onlyStockout) {
            $filters['only_stockout'] = true;
        }
        
        $products = $this->productRepository->search('', $filters);

        // Get categories with subcategories and counts
        $categoriesWithCounts = $this->getCategoriesWithCounts('', $selectedCategoryIds, $onlyStockout);

        return view('product.new-arrivals', compact('products', 'categoriesWithCounts', 'selectedCategoryIds'));
    }

    /**
     * Search products by name and tags
     */
    public function search(Request $request): View
    {
        $searchQuery = $request->get('search', '');
        
        // Handle multiple category filtering from checkboxes
        $selectedCategoryIds = $request->has('categories') && is_array($request->categories) 
            ? $request->categories 
            : [];

        $allCategoryIds = [];
        if (!empty($selectedCategoryIds)) {
            // Include subcategories when parent is selected
            foreach ($selectedCategoryIds as $catId) {
                $category = Category::find($catId);
                if ($category) {
                    $allCategoryIds[] = $category->id;
                    // Add subcategories
                    $subcategories = Category::where('parent_id', $category->id)->active()->pluck('id');
                    $allCategoryIds = array_merge($allCategoryIds, $subcategories->toArray());
                }
            }
            $allCategoryIds = array_unique($allCategoryIds);
        }

        $onlyStockout = $request->boolean('only_stockout');

        // Use repository for search
        $filters = ['per_page' => 20];
        if (!empty($allCategoryIds)) {
            $filters['category_ids'] = $allCategoryIds;
        }
        if ($onlyStockout) {
            $filters['only_stockout'] = true;
        } elseif (trim((string) ($searchQuery ?? '')) !== '') {
            $filters['include_out_of_stock'] = true;
        }

        if(!empty($request->input('sort'))) {
            $filters['sort'] = $request->input('sort');
        }

        $products = $this->productRepository->search($searchQuery ?? '', $filters);

        // Get categories with subcategories and counts
        $categoriesWithCounts = $this->getCategoriesWithCounts($searchQuery, $selectedCategoryIds, $onlyStockout);

        $gaSearchTerm = trim((string) $searchQuery);

        return view('product.search', compact('products', 'categoriesWithCounts', 'searchQuery', 'selectedCategoryIds', 'gaSearchTerm'));
    }
}
