<?php

namespace App\Http\Controllers\Portal;

use App\Http\Controllers\Controller;
use App\Http\Requests\Portal\StoreItemRequest;
use App\Http\Requests\Portal\UpdateItemRequest;
use App\Models\Category;
use App\Models\Item;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;

class ItemController extends Controller
{
    public function index(Request $request): View
    {
        $branchId = auth()->user()->active_branch_id;

        $query = Item::forBranch($branchId)->with(['category', 'variants']);

        if ($request->filled('category_id')) {
            $query->where('items.category_id', $request->category_id);
        }

        if ($request->filled('search')) {
            $query->where('items.name', 'like', '%'.$request->search.'%');
        }

        $items = $query->join('categories', 'items.category_id', '=', 'categories.id')
            ->select('items.*')
            ->orderBy('categories.sort_order')
            ->orderBy('items.sort_order')
            ->paginate(100);
        $categories = Category::forBranch($branchId)->whereNull('parent_id')->with('children')->get();

        return view('portal.items.index', compact('items', 'categories'));
    }

    public function create(): View
    {
        $branchId = auth()->user()->active_branch_id;
        $categories = Category::forBranch($branchId)->whereNull('parent_id')->with('children')->get();

        return view('portal.items.create', compact('categories'));
    }

    public function store(StoreItemRequest $request): RedirectResponse
    {
        $branchId = auth()->user()->active_branch_id;

        $validated = $request->validated();
        $validated['branch_id'] = $branchId;
        $validated['slug'] = Str::slug($validated['slug']);

        // Handle boolean defaults for toggles if not present (though requests should handle them)
        $validated['tax_inclusive'] = $request->boolean('tax_inclusive');
        $validated['available_dine_in'] = $request->boolean('available_dine_in', true);
        $validated['available_delivery'] = $request->boolean('available_delivery', true);
        $validated['available_takeaway'] = $request->boolean('available_takeaway', true);

        if ($request->hasFile('photo')) {
            $validated['image_path'] = $this->processImage($request->file('photo'));
        }

        DB::transaction(function () use ($validated, $request) {
            $item = Item::create($validated);

            if ($request->has('variants')) {
                foreach ($request->variants as $variant) {
                    $item->variants()->create($variant);
                }
            }
        });

        return redirect()->route('portal.items.create')
            ->with('success', 'Menu item created successfully.')
            ->with('last_category_id', $validated['category_id']);
    }

    public function edit(Item $item): View
    {
        $this->authorizeAccess($item);

        $branchId = auth()->user()->active_branch_id;
        $categories = Category::forBranch($branchId)->whereNull('parent_id')->with('children')->get();
        $item->load('variants');

        return view('portal.items.edit', compact('item', 'categories'));
    }

    public function update(UpdateItemRequest $request, Item $item): RedirectResponse
    {
        $this->authorizeAccess($item);

        $validated = $request->validated();
        $validated['slug'] = Str::slug($validated['slug']);

        $validated['tax_inclusive'] = $request->boolean('tax_inclusive');
        $validated['available_dine_in'] = $request->boolean('available_dine_in');
        $validated['available_delivery'] = $request->boolean('available_delivery');
        $validated['available_takeaway'] = $request->boolean('available_takeaway');

        if ($request->hasFile('photo')) {
            if ($item->image_path) {
                Storage::disk('public')->delete($item->image_path);
            }
            $validated['image_path'] = $this->processImage($request->file('photo'));
        }

        DB::transaction(function () use ($validated, $request, $item) {
            $item->update($validated);

            if ($request->has('variants')) {
                $variantIds = [];
                foreach ($request->variants as $variant) {
                    if (isset($variant['id'])) {
                        $v = $item->variants()->find($variant['id']);
                        if ($v) {
                            $v->update($variant);
                            $variantIds[] = $v->id;
                        }
                    } else {
                        $newV = $item->variants()->create($variant);
                        $variantIds[] = $newV->id;
                    }
                }
                // Delete variants not in the request
                $item->variants()->whereNotIn('id', $variantIds)->delete();
            } else {
                $item->variants()->delete();
            }
        });

        return redirect()->route('portal.items.index')->with('success', 'Menu item updated successfully.');
    }

    public function destroy(Item $item): RedirectResponse
    {
        $this->authorizeAccess($item);

        if ($item->image_path) {
            Storage::disk('public')->delete($item->image_path);
        }

        $item->delete();

        return redirect()->route('portal.items.index')->with('success', 'Menu item deleted successfully.');
    }

    /**
     * Process image: resize to maxWidth if necessary.
     */
    private function processImage($file, int $maxWidth = 500): string
    {
        $extension = strtolower($file->getClientOriginalExtension());
        $filename = Str::random(40).'.'.$extension;
        $folder = 'items';
        $fullPath = storage_path('app/public/'.$folder);

        if (! file_exists($fullPath)) {
            mkdir($fullPath, 0755, true);
        }

        $tempPath = $file->getRealPath();
        $imageInfo = @getimagesize($tempPath);

        if (! $imageInfo) {
            return $file->store($folder, 'public');
        }

        [$width, $height, $type] = $imageInfo;

        // If smaller than maxWidth, just store it normally
        if ($width <= $maxWidth) {
            return $file->store($folder, 'public');
        }

        $newWidth = $maxWidth;
        $newHeight = (int) ($height * ($maxWidth / $width));

        // Load image based on type
        $src = match ($type) {
            IMAGETYPE_JPEG => @imagecreatefromjpeg($tempPath),
            IMAGETYPE_PNG => @imagecreatefrompng($tempPath),
            IMAGETYPE_GIF => @imagecreatefromgif($tempPath),
            IMAGETYPE_WEBP => @imagecreatefromwebp($tempPath),
            default => null,
        };

        if (! $src) {
            return $file->store($folder, 'public');
        }

        $dst = imagescale($src, $newWidth, $newHeight);
        $savePath = $fullPath.'/'.$filename;

        // Save image based on type
        match ($type) {
            IMAGETYPE_JPEG => imagejpeg($dst, $savePath, 85),
            IMAGETYPE_PNG => imagepng($dst, $savePath),
            IMAGETYPE_GIF => imagegif($dst, $savePath),
            IMAGETYPE_WEBP => imagewebp($dst, $savePath, 85),
            default => imagejpeg($dst, $savePath, 85),
        };

        imagedestroy($src);
        imagedestroy($dst);

        return $folder.'/'.$filename;
    }

    /**
     * Ensure the user has access to the item.
     */
    protected function authorizeAccess(Item $item): void
    {
        if ($item->branch_id !== auth()->user()->active_branch_id) {
            abort(403, 'Unauthorized access to this menu item.');
        }
    }
}
