<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Ingredient;
use App\Models\Outlet;
use App\Models\OutletIngredient;
use App\Models\Supplier;
use App\Models\StockTransaction;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class IngredientController extends Controller
{
    /**
     * Display a listing of the ingredients.
     */
    public function index(Request $request): Response
    {
        $search = $request->input('search');

        $ingredients = Ingredient::with(['outletIngredients.outlet'])
            ->when($search, function ($query, $search) {
                $query->where('name', 'like', "%{$search}%");
            })
            ->latest()
            ->paginate(10)
            ->withQueryString();

        $outlets = Outlet::select('id', 'name')->get();
        $suppliers = Supplier::select('id', 'name')->get();

        $history = StockTransaction::with(['outlet', 'user', 'supplier', 'ingredient'])
            ->where('item_type', 'Ingredient')
            ->latest()
            ->paginate(10, ['*'], 'history_page')
            ->withQueryString();

        return Inertia::render('CafePOS/Ingredients/Index', [
            'ingredients' => $ingredients,
            'outlets' => $outlets,
            'suppliers' => $suppliers,
            'history' => $history,
            'filters' => [
                'search' => $search,
            ],
        ]);
    }

    /**
     * Store a newly created ingredient in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:ingredients'],
            'unit' => ['required', 'string', 'max:20'], // e.g. g, ml, pcs
        ]);

        $ingredient = Ingredient::create([
            'name' => $request->name,
            'unit' => $request->unit,
        ]);

        // Auto-initialize inventory record with 0 stock for all existing outlets
        $outlets = Outlet::all();
        foreach ($outlets as $outlet) {
            OutletIngredient::create([
                'outlet_id' => $outlet->id,
                'ingredient_id' => $ingredient->id,
                'stock_qty' => 0,
                'threshold_qty' => 0,
            ]);
        }

        activity()
            ->performedOn($ingredient)
            ->causedBy($request->user())
            ->log("Created ingredient: {$ingredient->name} ({$ingredient->unit})");

        return redirect()->back()->with('success', 'Ingredient created globally successfully.');
    }

    /**
     * Update the specified ingredient in storage.
     */
    public function update(Request $request, Ingredient $ingredient): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255', 'unique:ingredients,name,' . $ingredient->id],
            'unit' => ['required', 'string', 'max:20'],
        ]);

        $oldName = $ingredient->name;
        $ingredient->update([
            'name' => $request->name,
            'unit' => $request->unit,
        ]);

        activity()
            ->performedOn($ingredient)
            ->causedBy($request->user())
            ->log("Updated ingredient: {$oldName} -> {$ingredient->name}");

        return redirect()->back()->with('success', 'Ingredient updated successfully.');
    }

    /**
     * Remove the specified ingredient from storage.
     */
    public function destroy(Request $request, Ingredient $ingredient): RedirectResponse
    {
        $name = $ingredient->name;

        activity()
            ->performedOn($ingredient)
            ->causedBy($request->user())
            ->log("Deleted ingredient: {$name}");

        $ingredient->delete();

        return redirect()->back()->with('success', 'Ingredient deleted successfully.');
    }

    /**
     * Adjust / Restock stock levels for a specific ingredient in a specific outlet.
     */
    public function adjustStock(Request $request): RedirectResponse
    {
        $request->validate([
            'outlet_id' => ['required', 'integer', 'exists:outlets,id'],
            'ingredient_id' => ['required', 'integer', 'exists:ingredients,id'],
            'stock_qty' => ['required', 'numeric', 'min:0'],
            'threshold_qty' => ['required', 'numeric', 'min:0'],
            'action_type' => ['required', 'string', 'in:set,add'], // set directly, or add/restock
            'supplier_id' => ['nullable', 'integer', 'exists:suppliers,id'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $outletIngredient = OutletIngredient::firstOrCreate(
            [
                'outlet_id' => $request->outlet_id,
                'ingredient_id' => $request->ingredient_id,
            ],
            [
                'stock_qty' => 0,
                'threshold_qty' => 0,
            ]
        );

        $oldStock = $outletIngredient->stock_qty;

        if ($request->action_type === 'add') {
            $outletIngredient->stock_qty += $request->stock_qty;
        } else {
            $outletIngredient->stock_qty = $request->stock_qty;
        }

        $outletIngredient->threshold_qty = $request->threshold_qty;
        $outletIngredient->save();

        // Create stock transaction audit log
        StockTransaction::create([
            'outlet_id' => $request->outlet_id,
            'user_id' => $request->user()->id,
            'supplier_id' => $request->supplier_id,
            'item_type' => 'Ingredient',
            'item_id' => $request->ingredient_id,
            'qty' => $request->stock_qty,
            'type' => $request->action_type,
            'notes' => $request->notes,
        ]);

        $ingredient = Ingredient::find($request->ingredient_id);
        $outlet = Outlet::find($request->outlet_id);

        activity()
            ->performedOn($outletIngredient)
            ->causedBy($request->user())
            ->log("Adjusted stock for '{$ingredient->name}' in '{$outlet->name}': {$oldStock} -> {$outletIngredient->stock_qty}");

        return redirect()->back()->with('success', 'Stock level adjusted successfully.');
    }

    /**
     * Delete a specific stock transaction and revert its stock change (if applicable).
     */
    public function destroyTransaction(Request $request, StockTransaction $stockTransaction): RedirectResponse
    {
        if ($stockTransaction->item_type !== 'Ingredient') {
            abort(403, 'Unauthorized action.');
        }

        $outletIngredient = OutletIngredient::where('outlet_id', $stockTransaction->outlet_id)
            ->where('ingredient_id', $stockTransaction->item_id)
            ->first();

        $ingredient = Ingredient::find($stockTransaction->item_id);
        $outlet = Outlet::find($stockTransaction->outlet_id);
        $ingredientName = $ingredient ? $ingredient->name : 'Unknown Ingredient';
        $outletName = $outlet ? $outlet->name : 'Unknown Outlet';

        if ($stockTransaction->type === 'add' && $outletIngredient) {
            $oldStock = $outletIngredient->stock_qty;
            $outletIngredient->stock_qty = max(0, $outletIngredient->stock_qty - $stockTransaction->qty);
            $outletIngredient->save();

            activity()
                ->performedOn($outletIngredient)
                ->causedBy($request->user())
                ->log("Reverted stock adjustment on deletion for '{$ingredientName}' in '{$outletName}': {$oldStock} -> {$outletIngredient->stock_qty}");
        }

        activity()
            ->performedOn($stockTransaction)
            ->causedBy($request->user())
            ->log("Deleted stock transaction log: ID {$stockTransaction->id} for '{$ingredientName}' in '{$outletName}'");

        $stockTransaction->delete();

        return redirect()->back()->with('success', 'Stock transaction history deleted and inventory reverted successfully.');
    }
}
