<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\StockOpname;
use App\Models\StockOpnameItem;
use App\Models\Outlet;
use App\Models\Ingredient;
use App\Models\Product;
use App\Models\OutletIngredient;
use App\Models\OutletProduct;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;

class OpnameController extends Controller
{
    public function index(Request $request): Response
    {
        $user = $request->user();
        $outlets = Outlet::select('id', 'name')->get();
        
        $outletFilter = $request->input('outlet_id');
        $outletId = $user->outlet_id 
            ? (int)$user->outlet_id 
            : ($outletFilter 
                ? (int)$outletFilter 
                : ($outlets->first() ? $outlets->first()->id : null));

        $opnames = StockOpname::with(['outlet', 'user'])
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->latest()
            ->paginate(15)
            ->withQueryString();

        return Inertia::render('CafePOS/Opnames/Index', [
            'opnames' => $opnames,
            'outlets' => $outlets,
            'filters' => [
                'outlet_id' => $outletId ? (string)$outletId : null,
            ]
        ]);
    }

    public function show(StockOpname $opname): Response
    {
        $opname->load(['outlet', 'user', 'items']);
        
        $opnameItems = $opname->items->map(function ($item) {
            $unit = 'pcs';
            if ($item->item_type === 'Ingredient') {
                $unit = $item->item ? $item->item->unit : 'pcs';
            }
            return [
                'id' => $item->id,
                'item_type' => $item->item_type,
                'item_id' => $item->item_id,
                'name' => $item->item ? $item->item->name : 'Unknown',
                'system_qty' => (float)$item->system_qty,
                'actual_qty' => (float)$item->actual_qty,
                'difference_qty' => (float)$item->difference_qty,
                'unit' => $unit,
            ];
        });

        return Inertia::render('CafePOS/Opnames/Show', [
            'opname' => $opname,
            'items' => $opnameItems,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'outlet_id' => ['required', 'integer', 'exists:outlets,id'],
        ]);

        $user = $request->user();
        $outletId = (int)$request->outlet_id;

        if ($user->outlet_id && (int)$user->outlet_id !== $outletId) {
            return redirect()->back()->with('error', 'Unauthorized outlet access.');
        }

        try {
            DB::transaction(function () use ($outletId, $user) {
                $opname = StockOpname::create([
                    'outlet_id' => $outletId,
                    'user_id' => $user->id,
                    'status' => 'draft',
                ]);

                // Snapshot all current stock levels
                $ingredients = OutletIngredient::where('outlet_id', $outletId)->get();
                foreach ($ingredients as $ing) {
                    StockOpnameItem::create([
                        'stock_opname_id' => $opname->id,
                        'item_type' => 'Ingredient',
                        'item_id' => $ing->ingredient_id,
                        'system_qty' => $ing->stock_qty,
                        'actual_qty' => $ing->stock_qty,
                        'difference_qty' => 0,
                    ]);
                }

                $products = OutletProduct::where('outlet_id', $outletId)->get();
                foreach ($products as $prod) {
                    StockOpnameItem::create([
                        'stock_opname_id' => $opname->id,
                        'item_type' => 'Product',
                        'item_id' => $prod->product_id,
                        'system_qty' => $prod->stock_qty,
                        'actual_qty' => $prod->stock_qty,
                        'difference_qty' => 0,
                    ]);
                }
            });

            return redirect()->back()->with('success', 'Stock opname draft created successfully.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function complete(Request $request, StockOpname $opname): RedirectResponse
    {
        $request->validate([
            'items' => ['required', 'array'],
            'items.*.id' => ['required', 'integer', 'exists:stock_opname_items,id'],
            'items.*.actual_qty' => ['required', 'numeric', 'min:0'],
        ]);

        if ($opname->status === 'completed') {
            return redirect()->back()->with('error', 'Opname already completed.');
        }

        try {
            DB::transaction(function () use ($request, $opname) {
                foreach ($request->items as $itemData) {
                    $item = StockOpnameItem::findOrFail($itemData['id']);
                    $actual = (float)$itemData['actual_qty'];
                    $diff = $actual - (float)$item->system_qty;

                    $item->update([
                        'actual_qty' => $actual,
                        'difference_qty' => $diff,
                    ]);

                    // Apply adjustment to inventory
                    if ($item->item_type === 'Ingredient') {
                        $outletIng = OutletIngredient::where('outlet_id', $opname->outlet_id)
                            ->where('ingredient_id', $item->item_id)
                            ->first();
                        if ($outletIng) {
                            $outletIng->update(['stock_qty' => $actual]);
                        }
                    } else {
                        $outletProd = OutletProduct::where('outlet_id', $opname->outlet_id)
                            ->where('product_id', $item->item_id)
                            ->first();
                        if ($outletProd) {
                            $outletProd->update(['stock_qty' => $actual]);
                        }
                    }
                }

                $opname->update(['status' => 'completed']);
            });

            return redirect()->route('opnames.index')->with('success', 'Stock opname completed and inventory adjusted.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function destroy(StockOpname $opname): RedirectResponse
    {
        if ($opname->status === 'completed') {
            return redirect()->back()->with('error', 'Cannot delete completed opname.');
        }
        $opname->delete();
        return redirect()->back()->with('success', 'Stock opname deleted.');
    }
}
