<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Ingredient;
use App\Models\Outlet;
use App\Models\OutletProduct;
use App\Models\Product;
use App\Models\Recipe;
use App\Models\Supplier;
use App\Models\StockTransaction;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use Inertia\Response;

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

        $products = Product::with(['recipes.ingredient', 'outletProducts.outlet'])
            ->when($search, function ($query, $search) {
                $query->where('name', 'like', "%{$search}%");
            })
            ->when($category, function ($query, $category) {
                $query->where('category', $category);
            })
            ->orderBy('id', 'desc')
            ->paginate(10)
            ->withQueryString();

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

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

    /**
     * Store a newly created product in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        if (app()->environment('demo')) {
            return redirect()->back()->with('error', 'Mode Demo Aktif: Pembuatan produk baru tidak diizinkan di mode demo.');
        }
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'price' => ['required', 'numeric', 'min:0'],
            'category' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string'],
            'image' => ['nullable', 'image', 'max:2048', 'mimes:png,jpg,jpeg,webp'],
        ]);

        $imagePath = null;
        if ($request->hasFile('image')) {
            $path = $request->file('image')->store('products', 'public');
            $imagePath = Storage::disk('public')->url($path);
        }

        $product = Product::create([
            'name' => $request->name,
            'price' => $request->price,
            'category' => $request->category,
            'description' => $request->description,
            'image_path' => $imagePath,
            'is_active' => true,
        ]);

        // Auto-initialize retail stock records for all outlets
        $outlets = Outlet::all();
        foreach ($outlets as $outlet) {
            OutletProduct::create([
                'outlet_id' => $outlet->id,
                'product_id' => $product->id,
                'stock_qty' => 0,
                'threshold_qty' => 0,
            ]);
        }

        activity()
            ->performedOn($product)
            ->causedBy($request->user())
            ->log("Created product: {$product->name} (Rp " . number_format((float)$product->price, 0, ',', '.') . ")");

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

    /**
     * Update the specified product in storage.
     */
    public function update(Request $request, Product $product): RedirectResponse
    {
        if (app()->environment('demo')) {
            if ($request->hasFile('image')) {
                // Delete old image
                if ($product->image_path) {
                    $path = parse_url($product->image_path, PHP_URL_PATH);
                    if ($path) {
                        $relativePath = preg_replace('/^\/storage\//', '', $path);
                        if (Storage::disk('public')->exists($relativePath)) {
                            Storage::disk('public')->delete($relativePath);
                        }
                    }
                }

                $path = $request->file('image')->store('products', 'public');
                $imagePath = Storage::disk('public')->url($path);

                $product->update([
                    'image_path' => $imagePath,
                ]);

                activity()
                    ->performedOn($product)
                    ->causedBy($request->user())
                    ->log("Updated product image for: {$product->name} (Demo Mode)");

                return redirect()->back()->with('success', 'Product image uploaded successfully (Demo Mode: other fields were not modified).');
            }

            return redirect()->back()->with('error', 'Mode Demo Aktif: Pengubahan data produk tidak diizinkan tanpa unggahan gambar.');
        }

        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'price' => ['required', 'numeric', 'min:0'],
            'category' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string'],
            'image' => ['nullable', 'image', 'max:2048', 'mimes:png,jpg,jpeg,webp'],
            'is_active' => ['required', 'boolean'],
        ]);

        $imagePath = $product->image_path;
        if ($request->hasFile('image')) {
            // Delete old image
            if ($product->image_path) {
                $path = parse_url($product->image_path, PHP_URL_PATH);
                if ($path) {
                    $relativePath = preg_replace('/^\/storage\//', '', $path);
                    if (Storage::disk('public')->exists($relativePath)) {
                        Storage::disk('public')->delete($relativePath);
                    }
                }
            }

            $path = $request->file('image')->store('products', 'public');
            $imagePath = Storage::disk('public')->url($path);
        }

        $product->update([
            'name' => $request->name,
            'price' => $request->price,
            'category' => $request->category,
            'description' => $request->description,
            'image_path' => $imagePath,
            'is_active' => $request->is_active,
        ]);

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

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

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

        // Delete image
        if ($product->image_path) {
            $path = parse_url($product->image_path, PHP_URL_PATH);
            if ($path) {
                $relativePath = preg_replace('/^\/storage\//', '', $path);
                if (Storage::disk('public')->exists($relativePath)) {
                    Storage::disk('public')->delete($relativePath);
                }
            }
        }

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

        $product->delete();

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

    /**
     * Save recipe (Bill of Materials) for a product.
     */
    public function saveRecipe(Request $request, Product $product): RedirectResponse
    {
        $request->validate([
            'recipes' => ['nullable', 'array'],
            'recipes.*.ingredient_id' => ['required', 'integer', 'exists:ingredients,id'],
            'recipes.*.usage_qty' => ['required', 'numeric', 'gt:0'],
            'recipes.*.variant' => ['nullable', 'string', 'in:hot,ice'],
        ]);

        // Clear existing recipe mapping
        $product->recipes()->delete();

        // Insert new recipe items
        if ($request->has('recipes') && !empty($request->recipes)) {
            foreach ($request->recipes as $item) {
                Recipe::create([
                    'product_id' => $product->id,
                    'ingredient_id' => $item['ingredient_id'],
                    'usage_qty' => $item['usage_qty'],
                    'variant' => $item['variant'] ?? null,
                ]);
            }
        }

        activity()
            ->performedOn($product)
            ->causedBy($request->user())
            ->log("Updated recipe BOM for product: {$product->name}");

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

    /**
     * Adjust manual retail stock levels for a product in an outlet.
     */
    public function adjustProductStock(Request $request): RedirectResponse
    {
        $request->validate([
            'outlet_id' => ['required', 'integer', 'exists:outlets,id'],
            'product_id' => ['required', 'integer', 'exists:products,id'],
            'stock_qty' => ['required', 'numeric', 'min:0'],
            'threshold_qty' => ['required', 'numeric', 'min:0'],
            'action_type' => ['required', 'string', 'in:set,add'],
            'supplier_id' => ['nullable', 'integer', 'exists:suppliers,id'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $outletProduct = OutletProduct::firstOrCreate(
            [
                'outlet_id' => $request->outlet_id,
                'product_id' => $request->product_id,
            ],
            [
                'stock_qty' => 0,
                'threshold_qty' => 0,
            ]
        );

        $oldStock = $outletProduct->stock_qty;

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

        $outletProduct->threshold_qty = $request->threshold_qty;
        $outletProduct->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' => 'Product',
            'item_id' => $request->product_id,
            'qty' => $request->stock_qty,
            'type' => $request->action_type,
            'notes' => $request->notes,
        ]);

        $product = Product::find($request->product_id);
        $outlet = Outlet::find($request->outlet_id);

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

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