<?php

namespace App\Http\Controllers\Epelcon;

use App\Http\Controllers\Concerns\HandlesImageUploads;
use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Chef;
use App\Models\Cuisine;
use App\Models\DietaryPlan;
use App\Models\MenuCategory;
use App\Models\MenuItem;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class MenuController extends Controller
{
    use HandlesImageUploads;

    public const DIETARY_TAGS = ['vegan', 'vegetarian', 'halal', 'gluten_free', 'dairy_free', 'nut_free', 'low_carb', 'keto', 'diabetic_friendly'];

    public function index(Request $request)
    {
        $items = MenuItem::with(['category', 'cuisine', 'chef'])
            ->when($request->filled('type'), fn ($q) => $q->where('type', $request->type))
            ->when($request->filled('category'), fn ($q) => $q->where('menu_category_id', $request->category))
            ->when($request->filled('q'), fn ($q) => $q->where('name', 'like', '%' . $request->q . '%'))
            ->orderBy('name')
            ->paginate(18)->withQueryString();

        $cuisines = Cuisine::orderBy('name')->get();
        $categories = MenuCategory::orderBy('sort_order')->orderBy('name')->get();
        $chefs = Chef::where('status', 'active')->orderBy('name')->get();

        $counts = [
            'food' => MenuItem::where('type', 'food')->count(),
            'drink' => MenuItem::where('type', 'drink')->count(),
            'unavailable' => MenuItem::where('available', false)->count(),
        ];

        return view('epelcon.menu.index', compact('items', 'cuisines', 'categories', 'chefs', 'counts'))
            ->with('dietaryTags', self::DIETARY_TAGS);
    }

    public function storeItem(Request $request)
    {
        $data = $this->validateItem($request);
        $data['slug'] = Str::slug($data['name']) . '-' . Str::lower(Str::random(4));

        if ($image = $this->saveImage($request, 'image', 'menu')) {
            $data['image'] = $image;
        }

        MenuItem::create($data);
        ActivityLog::record('created menu item', 'menu', $data['name']);

        return back()->with('success', "“{$data['name']}” added to the menu.");
    }

    public function updateItem(Request $request, MenuItem $item)
    {
        $data = $this->validateItem($request);

        if ($image = $this->saveImage($request, 'image', 'menu')) {
            $data['image'] = $image;
        }

        $item->update($data);

        return back()->with('success', 'Menu item updated.');
    }

    public function toggleItem(MenuItem $item)
    {
        $item->update(['available' => ! $item->available]);

        return back()->with('success', $item->name . ($item->available ? ' is now available.' : ' marked unavailable.'));
    }

    public function destroyItem(MenuItem $item)
    {
        $name = $item->name;
        $item->delete();
        ActivityLog::record('deleted menu item', 'menu', $name);

        return back()->with('success', "“{$name}” removed.");
    }

    public function storeCuisine(Request $request)
    {
        $data = $request->validate(['name' => 'required|string|max:80', 'description' => 'nullable|string']);
        $data['slug'] = Str::slug($data['name']) . '-' . Str::lower(Str::random(4));

        Cuisine::create($data);

        return back()->with('success', "Cuisine “{$data['name']}” added.");
    }

    public function updateCuisine(Request $request, Cuisine $cuisine)
    {
        $data = $request->validate(['name' => 'required|string|max:80', 'description' => 'nullable|string', 'status' => 'required|in:active,inactive']);
        $cuisine->update($data);

        return back()->with('success', 'Cuisine updated.');
    }

    public function storeCategory(Request $request)
    {
        $data = $request->validate(['name' => 'required|string|max:80', 'type' => 'required|in:food,drink']);
        MenuCategory::create($data);

        return back()->with('success', "Category “{$data['name']}” added.");
    }

    public function chefs()
    {
        $chefs = Chef::with('user')->withCount('menuItems')->orderByDesc('featured')->orderBy('name')->get();
        $chefUsers = User::whereIn('role', ['chef', 'kitchen'])->where('status', 'active')->get(['id', 'name']);

        return view('epelcon.menu.chefs', compact('chefs', 'chefUsers'));
    }

    public function storeChef(Request $request)
    {
        $data = $this->validateChef($request);

        if ($photo = $this->saveImage($request, 'photo', 'chefs')) {
            $data['photo'] = $photo;
        }

        Chef::create($data);
        ActivityLog::record('created chef profile', 'menu', $data['name']);

        return back()->with('success', "Chef {$data['name']} added.");
    }

    public function updateChef(Request $request, Chef $chef)
    {
        $data = $this->validateChef($request);

        if ($photo = $this->saveImage($request, 'photo', 'chefs')) {
            $data['photo'] = $photo;
        }

        $chef->update($data);

        return back()->with('success', 'Chef profile updated.');
    }

    public function dietaryPlans()
    {
        $plans = DietaryPlan::orderBy('name')->get();

        return view('epelcon.menu.dietary', compact('plans'));
    }

    public function storeDietaryPlan(Request $request)
    {
        DietaryPlan::create($this->validateDietaryPlan($request));

        return back()->with('success', 'Dietary plan created.');
    }

    public function updateDietaryPlan(Request $request, DietaryPlan $plan)
    {
        $plan->update($this->validateDietaryPlan($request) + ['status' => $request->input('status', 'active')]);

        return back()->with('success', 'Dietary plan updated.');
    }

    private function validateItem(Request $request): array
    {
        $data = $request->validate([
            'name' => 'required|string|max:120',
            'menu_category_id' => 'nullable|exists:menu_categories,id',
            'cuisine_id' => 'nullable|exists:cuisines,id',
            'chef_id' => 'nullable|exists:chefs,id',
            'type' => 'required|in:food,drink',
            'description' => 'nullable|string',
            'price' => 'required|numeric|min:0',
            'cost' => 'nullable|numeric|min:0',
            'dietary_tags' => 'nullable|array',
            'dietary_tags.*' => 'in:' . implode(',', self::DIETARY_TAGS),
            'spice_level' => 'nullable|integer|min:0|max:5',
            'prep_time_minutes' => 'nullable|integer|min:0|max:480',
            'available' => 'nullable|boolean',
        ]);

        $data['station'] = $data['type'] === 'drink' ? 'bar' : 'kitchen';
        $data['cost'] = $data['cost'] ?? 0;
        $data['spice_level'] = $data['spice_level'] ?? 0;
        $data['prep_time_minutes'] = $data['prep_time_minutes'] ?? 15;
        $data['available'] = $request->boolean('available', true);
        $data['dietary_tags'] = $data['dietary_tags'] ?? [];

        return $data;
    }

    private function validateChef(Request $request): array
    {
        return $request->validate([
            'name' => 'required|string|max:120',
            'user_id' => 'nullable|exists:users,id',
            'title' => 'nullable|string|max:80',
            'bio' => 'nullable|string',
            'specialties' => 'nullable|string|max:255',
            'years_experience' => 'nullable|integer|min:0|max:80',
            'rating' => 'nullable|numeric|min:0|max:5',
            'featured' => 'nullable|boolean',
            'status' => 'nullable|in:active,inactive',
        ]) + ['featured' => $request->boolean('featured'), 'status' => $request->input('status', 'active')];
    }

    private function validateDietaryPlan(Request $request): array
    {
        return $request->validate([
            'name' => 'required|string|max:120',
            'description' => 'nullable|string',
            'goal' => 'nullable|string|max:150',
            'daily_calories' => 'nullable|integer|min:0|max:10000',
            'price' => 'required|numeric|min:0',
            'duration_days' => 'required|integer|min:1|max:365',
        ]);
    }
}
