<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Brand;
use App\Models\Category;
use App\Models\Product;
use App\Models\TaxRate;
use App\Models\Unit;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;

class ProductController extends Controller
{
    public function index(Request $request): View|JsonResponse
    {
        // Handle AJAX requests
        if ($request->ajax() || $request->has('ajax')) {
            return $this->getProducts($request);
        }

        return view('admin.products.product.index');
    }

    private function getProducts(Request $request): JsonResponse
    {
        $query = Product::with(['category', 'brand', 'unit', 'tax']);

        // Filter by type (product/service)
        if ($request->has('type') && $request->type !== 'all') {
            $query->where('type', $request->type);
        }

        // Search functionality
        if ($request->has('search') && ! empty($request->search)) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('code', 'like', "%{$search}%")
                    ->orWhere('barcode', 'like', "%{$search}%")
                    ->orWhereHas('category', function ($q) use ($search) {
                        $q->where('name', 'like', "%{$search}%");
                    })
                    ->orWhereHas('brand', function ($q) use ($search) {
                        $q->where('name', 'like', "%{$search}%");
                    });
            });
        }

        // Get per page value
        $perPage = $request->get('per_page', 10);
        $perPage = in_array($perPage, [10, 25, 50, 100]) ? $perPage : 10;

        // Paginate results
        $products = $query->orderBy('created_at', 'desc')->paginate($perPage);

        return response()->json([
            'products' => $products->map(function ($product) {
                return [
                    'id' => $product->id,
                    'name' => $product->name ?? 'N/A',
                    'code' => $product->code ?? null,
                    'type' => $product->type ?? 'product',
                    'image' => $product->image ? asset('storage/'.$product->image) : null,
                    'category' => $product->category ? $product->category->name : null,
                    'brand' => $product->brand ? $product->brand->name : null,
                    'selling_price' => number_format($product->selling_price ?? 0, 2),
                    'stock' => $product->stock ?? 0,
                    'alert_quantity' => $product->alert_quantity ?? 0,
                    'status' => $product->status ?? false,
                ];
            }),
            'pagination' => [
                'current_page' => $products->currentPage(),
                'last_page' => $products->lastPage(),
                'per_page' => $products->perPage(),
                'total' => $products->total(),
                'from' => $products->firstItem() ?? 0,
                'to' => $products->lastItem() ?? 0,
            ],
        ]);
    }

    public function create(): View
    {
        return view('admin.products.product.create', $this->productFormDropdownData());
    }

    public function store(Request $request)
    {
        // Validate the request
        $rules = [
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|max:255|unique:products,code',
            'type' => 'required|in:product,service',
            'description' => 'nullable|string',
            'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:5120', // 5MB max
            'category_id' => 'nullable|exists:categories,id',
            'brand_id' => 'nullable|exists:brands,id',
            'unit_id' => 'nullable|exists:units,id',
            'tax_id' => 'nullable|exists:tax_rates,id',
            'selling_price' => 'required|numeric|min:0',
            'purchase_price' => 'required|numeric|min:0',
            'discount_type' => 'nullable|in:fixed,percentage',
            'discount_value' => 'nullable|numeric|min:0',
            'barcode' => 'nullable|string|max:255|unique:products,barcode',
            'stock' => 'nullable|integer|min:0',
            'alert_quantity' => 'nullable|integer|min:0',
            'status' => 'nullable|boolean',
            'gallery' => 'nullable|array',
            'gallery.*' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:5120',
        ];

        // Make category_id, brand_id, and unit_id required if type is product
        if ($request->type === 'product') {
            $rules['category_id'] = 'required|exists:categories,id';
            $rules['brand_id'] = 'required|exists:brands,id';
            $rules['unit_id'] = 'required|exists:units,id';
        }

        $validated = $request->validate($rules);
        $validated['stock'] = (int) ($validated['stock'] ?? 0);

        try {
            // Handle product image upload
            $imagePath = null;
            if ($request->hasFile('image')) {
                $image = $request->file('image');
                $imageName = time().'_'.Str::random(10).'.'.$image->getClientOriginalExtension();
                $imagePath = $image->storeAs('products', $imageName, 'public');
            }

            // Create the product
            $product = Product::create([
                'name' => $validated['name'],
                'code' => $validated['code'] ?? null,
                'type' => $validated['type'],
                'description' => $validated['description'] ?? null,
                'image' => $imagePath,
                'category_id' => $validated['category_id'] ?? null,
                'brand_id' => $validated['brand_id'] ?? null,
                'unit_id' => $validated['unit_id'] ?? null,
                'tax_id' => $validated['tax_id'] ?? null,
                'selling_price' => $validated['selling_price'],
                'purchase_price' => $validated['purchase_price'],
                'discount_type' => $validated['discount_type'] ?? null,
                'discount_value' => $validated['discount_value'] ?? 0,
                'barcode' => $validated['barcode'] ?? null,
                'stock' => $validated['stock'],
                'alert_quantity' => $validated['alert_quantity'] ?? 0,
                'status' => $request->has('status') ? (bool) $request->status : true,
                'created_by' => Auth::id(),
            ]);

            // Handle gallery images upload
            $galleryImages = [];
            if ($request->hasFile('gallery')) {
                foreach ($request->file('gallery') as $galleryImage) {
                    if ($galleryImage->isValid()) {
                        $galleryName = time().'_'.Str::random(10).'_'.$galleryImage->getClientOriginalName();
                        $galleryPath = $galleryImage->storeAs('products/gallery', $galleryName, 'public');
                        $galleryImages[] = $galleryPath;
                    }
                }
            }

            // Update product with gallery images if any
            if (! empty($galleryImages)) {
                $product->update(['gallery_images' => $galleryImages]);
            }

            return redirect()->route('admin.products.index')
                ->with('success', ucfirst($product->type).' created successfully!');

        } catch (\Exception $e) {
            return redirect()->back()
                ->withInput()
                ->with('error', 'Error creating product: '.$e->getMessage());
        }
    }

    public function show($id): View
    {
        $product = Product::with(['category', 'brand', 'unit', 'tax'])->findOrFail($id);

        return view('admin.products.product.show', compact('product'));
    }

    public function edit($id): View
    {
        $product = Product::with(['category', 'brand', 'unit', 'tax'])->findOrFail($id);

        return view('admin.products.product.edit', array_merge(
            ['product' => $product],
            $this->productFormDropdownData($product)
        ));
    }

    /**
     * Lists for product create/edit selects (server-rendered so dropdowns work without JS fetch).
     */
    private function productFormDropdownData(?Product $product = null): array
    {
        $categories = Category::query()
            ->when(! $product, fn ($q) => $q->where('is_active', true))
            ->when($product, fn ($q) => $q->where(function ($q) use ($product) {
                $q->where('is_active', true);
                if ($product->category_id) {
                    $q->orWhere('id', $product->category_id);
                }
            }))
            ->orderBy('name')
            ->get(['id', 'name']);

        $brands = Brand::query()
            ->when(! $product, fn ($q) => $q->where('is_active', true))
            ->when($product, fn ($q) => $q->where(function ($q) use ($product) {
                $q->where('is_active', true);
                if ($product->brand_id) {
                    $q->orWhere('id', $product->brand_id);
                }
            }))
            ->orderBy('name')
            ->get(['id', 'name']);

        $units = Unit::query()
            ->when(! $product, fn ($q) => $q->where('is_active', true))
            ->when($product, fn ($q) => $q->where(function ($q) use ($product) {
                $q->where('is_active', true);
                if ($product->unit_id) {
                    $q->orWhere('id', $product->unit_id);
                }
            }))
            ->orderBy('name')
            ->get(['id', 'name', 'short_name']);

        $taxes = TaxRate::query()
            ->when(! $product, fn ($q) => $q->where('is_active', true))
            ->when($product, fn ($q) => $q->where(function ($q) use ($product) {
                $q->where('is_active', true);
                if ($product->tax_id) {
                    $q->orWhere('id', $product->tax_id);
                }
            }))
            ->orderBy('name')
            ->get(['id', 'name', 'rate']);

        return compact('categories', 'brands', 'units', 'taxes');
    }

    public function update(Request $request, $id)
    {
        $product = Product::findOrFail($id);

        // Validate the request
        $rules = [
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|max:255|unique:products,code,'.$id,
            'type' => 'required|in:product,service',
            'description' => 'nullable|string',
            'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:5120',
            'category_id' => 'nullable|exists:categories,id',
            'brand_id' => 'nullable|exists:brands,id',
            'unit_id' => 'nullable|exists:units,id',
            'tax_id' => 'nullable|exists:tax_rates,id',
            'selling_price' => 'required|numeric|min:0',
            'purchase_price' => 'required|numeric|min:0',
            'discount_type' => 'nullable|in:fixed,percentage',
            'discount_value' => 'nullable|numeric|min:0',
            'barcode' => 'nullable|string|max:255|unique:products,barcode,'.$id,
            'stock' => 'nullable|integer|min:0',
            'alert_quantity' => 'nullable|integer|min:0',
            'status' => 'nullable|boolean',
            'gallery' => 'nullable|array',
            'gallery.*' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:5120',
        ];

        if ($request->type === 'product') {
            $rules['category_id'] = 'required|exists:categories,id';
            $rules['brand_id'] = 'required|exists:brands,id';
            $rules['unit_id'] = 'required|exists:units,id';
        }

        $validated = $request->validate($rules);
        $validated['stock'] = (int) ($validated['stock'] ?? 0);

        try {
            // Handle product image upload
            if ($request->hasFile('image')) {
                // Delete old image if exists
                if ($product->image && Storage::disk('public')->exists($product->image)) {
                    Storage::disk('public')->delete($product->image);
                }

                $image = $request->file('image');
                $imageName = time().'_'.Str::random(10).'.'.$image->getClientOriginalExtension();
                $imagePath = $image->storeAs('products', $imageName, 'public');
                $validated['image'] = $imagePath;
            }

            // Handle gallery images upload
            if ($request->hasFile('gallery')) {
                $galleryImages = $product->gallery_images ?? [];
                foreach ($request->file('gallery') as $galleryImage) {
                    if ($galleryImage->isValid()) {
                        $galleryName = time().'_'.Str::random(10).'_'.$galleryImage->getClientOriginalName();
                        $galleryPath = $galleryImage->storeAs('products/gallery', $galleryName, 'public');
                        $galleryImages[] = $galleryPath;
                    }
                }
                $validated['gallery_images'] = $galleryImages;
            }

            $product->update($validated);

            return redirect()->route('admin.products.index')
                ->with('success', ucfirst($product->type).' updated successfully!');

        } catch (\Exception $e) {
            return redirect()->back()
                ->withInput()
                ->with('error', 'Error updating product: '.$e->getMessage());
        }
    }

    public function updateStatus(Request $request, $id): JsonResponse
    {
        try {
            $product = Product::findOrFail($id);
            $product->status = $request->input('status', ! $product->status);
            $product->save();

            return response()->json([
                'success' => true,
                'message' => 'Product status updated successfully',
                'status' => $product->status,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error updating status: '.$e->getMessage(),
            ], 500);
        }
    }

    public function destroy($id)
    {
        try {
            $product = Product::findOrFail($id);

            // Delete product image if exists
            if ($product->image && Storage::disk('public')->exists($product->image)) {
                Storage::disk('public')->delete($product->image);
            }

            // Delete gallery images if exist
            if ($product->gallery_images && is_array($product->gallery_images)) {
                foreach ($product->gallery_images as $galleryImage) {
                    if (Storage::disk('public')->exists($galleryImage)) {
                        Storage::disk('public')->delete($galleryImage);
                    }
                }
            }

            $product->delete();

            if (request()->ajax() || request()->wantsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Product deleted successfully',
                ]);
            }

            return redirect()->route('admin.products.index')
                ->with('success', 'Product deleted successfully');

        } catch (\Exception $e) {
            if (request()->ajax() || request()->wantsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Error deleting product: '.$e->getMessage(),
                ], 500);
            }

            return redirect()->route('admin.products.index')
                ->with('error', 'Error deleting product: '.$e->getMessage());
        }
    }
}
