<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\Product;
use App\Traits\ProductFormattingTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;

class ProductController extends Controller
{
    use ProductFormattingTrait;

    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): JsonResponse
    {
        $query = Product::with(['categoryRelation.parent']);

        // Smart category filtering - works for both main categories and subcategories
        if ($request->has('category_id')) {
            $categoryId = $request->category_id;
            
            // Validate category exists
            $category = Category::where('id', $categoryId)->first();
            if (!$category) {
                return response()->json([
                    'success' => false,
                    'message' => "Category with ID {$categoryId} not found",
                    'data' => [],
                ], 404);
            }
            
            // If it's a main category, include products from ALL subcategories
            if ($category->isMainCategory()) {
                $query->whereHas('categoryRelation', function ($q) use ($categoryId) {
                    $q->where(function ($subQ) use ($categoryId) {
                        $subQ->where('id', $categoryId)
                            ->orWhere('parent_id', $categoryId);
                    });
                });
            } else {
                // If it's a subcategory, only filter by this specific subcategory
                $query->where('category_id', $categoryId);
            }
        }

        // Alternative: Filter by subcategory_id only (must be a subcategory)
        if ($request->has('subcategory_id')) {
            $subcategoryId = $request->subcategory_id;
            
            // Validate subcategory exists and is actually a subcategory
            $subcategory = Category::where('id', $subcategoryId)->first();
            if (!$subcategory) {
                return response()->json([
                    'success' => false,
                    'message' => "Subcategory with ID {$subcategoryId} not found",
                    'data' => [],
                ], 404);
            }
            
            if ($subcategory->isMainCategory()) {
                return response()->json([
                    'success' => false,
                    'message' => "Category ID {$subcategoryId} is a main category, not a subcategory. Use category_id instead.",
                    'data' => [],
                ], 400);
            }
            
            $query->where('category_id', $subcategoryId);
        }

        // Alternative: Filter by main category only (must be a main category)
        if ($request->has('main_category_id')) {
            $mainCategoryId = $request->main_category_id;
            
            // Validate main category exists
            $mainCategory = Category::where('id', $mainCategoryId)->first();
            if (!$mainCategory) {
                return response()->json([
                    'success' => false,
                    'message' => "Category with ID {$mainCategoryId} not found",
                    'data' => [],
                ], 404);
            }
            
            if ($mainCategory->isSubcategory()) {
                return response()->json([
                    'success' => false,
                    'message' => "Category ID {$mainCategoryId} is a subcategory, not a main category. Use category_id instead.",
                    'data' => [],
                ], 400);
            }
            
            $query->whereHas('categoryRelation', function ($q) use ($mainCategoryId) {
                $q->where(function ($subQ) use ($mainCategoryId) {
                    // Direct match or subcategory of the main category
                    $subQ->where('id', $mainCategoryId)
                        ->orWhere('parent_id', $mainCategoryId);
                });
            });
        }

        // Filter by category (legacy - using category code)
        if ($request->has('category')) {
            $query->where('category', $request->category);
        }

        // Filter by in_stock
        if ($request->has('in_stock')) {
            $query->where('in_stock', filter_var($request->in_stock, FILTER_VALIDATE_BOOLEAN));
        }

        // Filter by on_sale
        if ($request->has('on_sale')) {
            $query->where('on_sale', filter_var($request->on_sale, FILTER_VALIDATE_BOOLEAN));
        }

        // Search by name
        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('name_km', 'like', "%{$search}%");
            });
        }

        // Sorting
        $sortBy = $request->get('sort_by', 'created_at');
        $sortOrder = $request->get('sort_order', 'desc');
        $sortBy = in_array($sortBy, ['name', 'price', 'original_price', 'created_at', 'updated_at'], true) ? $sortBy : 'created_at';
        $sortOrder = strtolower((string) $sortOrder) === 'asc' ? 'asc' : 'desc';
        $query->orderBy($sortBy, $sortOrder);

        // Pagination
        $perPage = min(100, max(1, (int) $request->get('per_page', 15)));
        $products = $query->paginate($perPage);

        return response()->json([
            'success' => true,
            'data' => $this->formatPaginatedResponse($products, auth()->id()),
        ]);
    }

    public function sales(Request $request): JsonResponse
    {
        $query = Product::with(['categoryRelation.parent']);
    
        // Smart category filtering
        if ($request->has('category_id')) {
            $categoryId = $request->category_id;
    
            $category = Category::find($categoryId);
            if (!$category) {
                return response()->json([
                    'success' => false,
                    'message' => "Category with ID {$categoryId} not found",
                    'data' => [],
                ], 404);
            }
    
            if ($category->isMainCategory()) {
                $query->whereHas('categoryRelation', function ($q) use ($categoryId) {
                    $q->where(function ($subQ) use ($categoryId) {
                        $subQ->where('id', $categoryId)
                             ->orWhere('parent_id', $categoryId);
                    });
                });
            } else {
                $query->where('category_id', $categoryId);
            }
        }
    
        // Filter by subcategory
        if ($request->has('subcategory_id')) {
            $subcategoryId = $request->subcategory_id;
    
            $subcategory = Category::find($subcategoryId);
            if (!$subcategory) {
                return response()->json([
                    'success' => false,
                    'message' => "Subcategory with ID {$subcategoryId} not found",
                    'data' => [],
                ], 404);
            }
    
            if ($subcategory->isMainCategory()) {
                return response()->json([
                    'success' => false,
                    'message' => "Category ID {$subcategoryId} is a main category. Use category_id instead.",
                    'data' => [],
                ], 400);
            }
    
            $query->where('category_id', $subcategoryId);
        }
    
        // Filter by main category only
        if ($request->has('main_category_id')) {
            $mainCategoryId = $request->main_category_id;
    
            $mainCategory = Category::find($mainCategoryId);
            if (!$mainCategory) {
                return response()->json([
                    'success' => false,
                    'message' => "Category with ID {$mainCategoryId} not found",
                    'data' => [],
                ], 404);
            }
    
            if ($mainCategory->isSubcategory()) {
                return response()->json([
                    'success' => false,
                    'message' => "Category ID {$mainCategoryId} is a subcategory. Use category_id instead.",
                    'data' => [],
                ], 400);
            }
    
            $query->whereHas('categoryRelation', function ($q) use ($mainCategoryId) {
                $q->where(function ($subQ) use ($mainCategoryId) {
                    $subQ->where('id', $mainCategoryId)
                         ->orWhere('parent_id', $mainCategoryId);
                });
            });
        }
    
        // Legacy category filter
        if ($request->has('category')) {
            $query->where('category', $request->category);
        }
    
        // In stock only
        $query->where('in_stock', true);
    
       
        $query->where('on_sale', true);

    
        // Search
        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('name_km', 'like', "%{$search}%");
            });
        }
    
        // Sorting
        $sortBy = $request->get('sort_by', 'created_at');
        $sortOrder = $request->get('sort_order', 'desc');
        $sortBy = in_array($sortBy, ['name', 'price', 'original_price', 'created_at', 'updated_at'], true) ? $sortBy : 'created_at';
        $sortOrder = strtolower((string) $sortOrder) === 'asc' ? 'asc' : 'desc';
    
        // Limit (default 5)
        $limit = min(100, max(1, (int) $request->get('limit', 5)));
    
        $products = $query
            ->orderBy($sortBy, $sortOrder)
            ->limit($limit)
            ->get();
    
        return response()->json([
            'success' => true,
            'data' => $products,
        ]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'name_km' => 'nullable|string|max:255',
            'price' => 'required|numeric|min:0',
            'original_price' => 'nullable|numeric|min:0',
            'category' => 'nullable|string|max:255', // Legacy field, optional now
            'category_id' => 'nullable|exists:categories,id',
            'description' => 'nullable|string',
            'description_km' => 'nullable|string',
            'short_description' => 'nullable|string|max:500',
            'short_description_km' => 'nullable|string|max:500',
            'in_stock' => 'nullable|boolean',
            'on_sale' => 'nullable|boolean',
            'images' => 'nullable|array',
            'images.*' => 'nullable|string',
        ]);

        // Require either category_id or category (legacy)
        if (! $request->has('category_id') && ! $request->has('category')) {
            return response()->json([
                'success' => false,
                'errors' => ['category_id' => ['Either category_id or category is required']],
            ], 422);
        }

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $product = Product::create($validator->validated());
        $product->load(['categoryRelation.parent']);

        return response()->json([
            'success' => true,
            'message' => 'Product created successfully',
            'data' => $this->formatProductResponse($product, auth()->id()),
        ], 201);
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id): JsonResponse
    {
        $product = Product::with(['categoryRelation.parent'])->find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        return response()->json([
            'success' => true,
            'data' => $this->formatProductResponse($product, auth()->id()),
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|required|string|max:255',
            'name_km' => 'nullable|string|max:255',
            'price' => 'sometimes|required|numeric|min:0',
            'original_price' => 'nullable|numeric|min:0',
            'category' => 'nullable|string|max:255', // Legacy field, optional now
            'category_id' => 'nullable|exists:categories,id',
            'description' => 'nullable|string',
            'description_km' => 'nullable|string',
            'short_description' => 'nullable|string|max:500',
            'short_description_km' => 'nullable|string|max:500',
            'in_stock' => 'nullable|boolean',
            'on_sale' => 'nullable|boolean',
            'images' => 'nullable|array',
            'images.*' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $product->update($validator->validated());
        $product->load(['categoryRelation.parent']);

        return response()->json([
            'success' => true,
            'message' => 'Product updated successfully',
            'data' => $this->formatProductResponse($product->fresh(['categoryRelation.parent']), auth()->id()),
        ]);
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        // Delete associated images
        if ($product->images) {
            foreach ($product->images as $image) {
                if ($image) {
                    // Remove /storage/ prefix if present
                    $imagePath = str_replace('/storage/', '', $image);
                    if (Storage::disk('public')->exists($imagePath)) {
                        Storage::disk('public')->delete($imagePath);
                    }
                }
            }
        }

        $product->delete();

        return response()->json([
            'success' => true,
            'message' => 'Product deleted successfully',
        ]);
    }

    /**
     * Upload product images.
     */
    public function uploadImages(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'images' => 'required|array|min:1|max:10',
            'images.*' => 'required|image|mimes:jpeg,png,jpg,gif,webp|max:5120', // 5MB max
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $uploadedImages = [];

        foreach ($request->file('images') as $image) {
            $filename = time().'-'.uniqid().'.'.$image->getClientOriginalExtension();
            $path = $image->storeAs('uploads', $filename, 'public');
            $uploadedImages[] = '/storage/'.$path;
        }

        return response()->json([
            'success' => true,
            'message' => 'Images uploaded successfully',
            'data' => [
                'images' => $uploadedImages,
            ],
        ]);
    }

    /**
     * Upload a single image (for color variants).
     */
    public function uploadImage(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'image' => 'required|image|mimes:jpeg,png,jpg,gif,webp|max:5120', // 5MB max
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $image = $request->file('image');
        $filename = time().'-'.uniqid().'.'.$image->getClientOriginalExtension();
        $path = $image->storeAs('uploads', $filename, 'public');

        return response()->json([
            'success' => true,
            'message' => 'Image uploaded successfully',
            'data' => [
                'image' => '/storage/'.$path,
            ],
        ]);
    }

    /**
     * Add images to a product's gallery.
     */
    public function addImages(Request $request, string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'images' => 'required|array|min:1|max:10',
            'images.*' => 'required|image|mimes:jpeg,png,jpg,gif,webp|max:5120',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $currentImages = $product->images ?? [];
        $uploadedImages = [];

        foreach ($request->file('images') as $image) {
            $filename = time().'-'.uniqid().'.'.$image->getClientOriginalExtension();
            $path = $image->storeAs('uploads/products', $filename, 'public');
            $imageUrl = '/storage/'.$path;
            $uploadedImages[] = $imageUrl;
        }

        // Merge new images with existing ones
        $allImages = array_merge($currentImages, $uploadedImages);
        $product->update(['images' => $allImages]);

        return response()->json([
            'success' => true,
            'message' => 'Images added to product gallery successfully',
            'data' => [
                'product_id' => $product->id,
                'new_images' => $uploadedImages,
                'total_images' => count($allImages),
                'all_images' => $allImages,
            ],
        ]);
    }

    /**
     * Remove an image from a product's gallery.
     */
    public function removeImage(Request $request, string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'image_url' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $imageUrl = $request->input('image_url');
        $currentImages = $product->images ?? [];

        // Find and remove the image
        $key = array_search($imageUrl, $currentImages);
        if ($key !== false) {
            // Delete the file from storage
            $imagePath = str_replace('/storage/', '', $imageUrl);
            if (Storage::disk('public')->exists($imagePath)) {
                Storage::disk('public')->delete($imagePath);
            }

            // Remove from array
            unset($currentImages[$key]);
            $currentImages = array_values($currentImages); // Re-index array

            $product->update(['images' => $currentImages]);

            return response()->json([
                'success' => true,
                'message' => 'Image removed from product gallery successfully',
                'data' => [
                    'product_id' => $product->id,
                    'removed_image' => $imageUrl,
                    'remaining_images' => $currentImages,
                    'total_images' => count($currentImages),
                ],
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Image not found in product gallery',
        ], 404);
    }

    /**
     * Set a featured/main image for the product.
     */
    public function setFeaturedImage(Request $request, string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'image_url' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $imageUrl = $request->input('image_url');
        $currentImages = $product->images ?? [];

        // Check if image exists in gallery
        if (! in_array($imageUrl, $currentImages)) {
            return response()->json([
                'success' => false,
                'message' => 'Image not found in product gallery',
            ], 404);
        }

        // Move featured image to first position
        $key = array_search($imageUrl, $currentImages);
        unset($currentImages[$key]);
        array_unshift($currentImages, $imageUrl);
        $currentImages = array_values($currentImages);

        $product->update(['images' => $currentImages]);

        return response()->json([
            'success' => true,
            'message' => 'Featured image set successfully',
            'data' => [
                'product_id' => $product->id,
                'featured_image' => $imageUrl,
                'all_images' => $currentImages,
            ],
        ]);
    }

    /**
     * Reorder images in a product's gallery.
     */
    public function reorderImages(Request $request, string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'image_urls' => 'required|array|min:1',
            'image_urls.*' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $newOrder = $request->input('image_urls');
        $currentImages = $product->images ?? [];

        // Validate all images exist in current gallery
        foreach ($newOrder as $imageUrl) {
            if (! in_array($imageUrl, $currentImages)) {
                return response()->json([
                    'success' => false,
                    'message' => "Image not found in product gallery: {$imageUrl}",
                ], 404);
            }
        }

        // Ensure all current images are included (add any missing ones at the end)
        $missingImages = array_diff($currentImages, $newOrder);
        $finalOrder = array_merge($newOrder, $missingImages);

        $product->update(['images' => $finalOrder]);

        return response()->json([
            'success' => true,
            'message' => 'Images reordered successfully',
            'data' => [
                'product_id' => $product->id,
                'images' => $finalOrder,
            ],
        ]);
    }

    /**
     * Get product gallery images.
     */
    public function getGallery(string $id): JsonResponse
    {
        $product = Product::find($id);

        if (! $product) {
            return response()->json([
                'success' => false,
                'message' => 'Product not found',
            ], 404);
        }

        $images = $product->images ?? [];
        $featuredImage = ! empty($images) ? $images[0] : null;

        return response()->json([
            'success' => true,
            'data' => [
                'product_id' => $product->id,
                'product_name' => $product->name,
                'featured_image' => $featuredImage,
                'total_images' => count($images),
                'images' => $images,
            ],
        ]);
    }
}
