<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderItem;
use App\Models\Outlet;
use App\Models\Supplier;
use App\Models\Ingredient;
use App\Models\OutletIngredient;
use App\Models\StockTransaction;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class PurchaseOrderController extends Controller
{
    public function index(Request $request): Response
    {
        $user = $request->user();
        $outletFilter = $request->input('outlet_id');
        $statusFilter = $request->input('status');

        $outletId = $user->outlet_id 
            ? (int)$user->outlet_id 
            : ($outletFilter ? (int)$outletFilter : null);

        $purchaseOrders = PurchaseOrder::with(['outlet', 'supplier', 'items.ingredient'])
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->when($statusFilter, fn($q) => $q->where('status', $statusFilter))
            ->latest()
            ->get();

        $outlets = Outlet::select('id', 'name')->get();
        $suppliers = Supplier::select('id', 'name')->get();
        
        // Fetch all active ingredients for drop-downs
        $ingredients = Ingredient::select('id', 'name', 'purchase_price', 'unit')->get();

        return Inertia::render('CafePOS/PurchaseOrders/Index', [
            'purchaseOrders' => $purchaseOrders,
            'outlets' => $outlets,
            'suppliers' => $suppliers,
            'ingredients' => $ingredients,
            'isCashier' => !is_null($user->outlet_id),
            'filters' => [
                'outlet_id' => $outletFilter,
                'status' => $statusFilter,
            ]
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'outlet_id' => ['required', 'integer', 'exists:outlets,id'],
            'supplier_id' => ['required', 'integer', 'exists:suppliers,id'],
            'notes' => ['nullable', 'string'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.ingredient_id' => ['required', 'integer', 'exists:ingredients,id'],
            'items.*.qty' => ['required', 'numeric', 'min:0.0001'],
            'items.*.price' => ['required', 'numeric', 'min:0'],
        ]);

        try {
            DB::transaction(function () use ($request) {
                // Generate PO Number: PO-YYYYMMDD-XXXX
                $datePart = date('Ymd');
                $randomPart = rand(1000, 9999);
                $poNumber = "PO-{$datePart}-{$randomPart}";

                $totalAmount = 0.0;
                $itemsData = [];

                foreach ($request->items as $item) {
                    $subtotal = (float)$item['qty'] * (float)$item['price'];
                    $totalAmount += $subtotal;

                    $itemsData[] = [
                        'ingredient_id' => (int)$item['ingredient_id'],
                        'qty' => (float)$item['qty'],
                        'price' => (float)$item['price'],
                        'subtotal' => $subtotal,
                    ];
                }

                $purchaseOrder = PurchaseOrder::create([
                    'po_number' => $poNumber,
                    'outlet_id' => (int)$request->outlet_id,
                    'supplier_id' => (int)$request->supplier_id,
                    'notes' => $request->notes,
                    'total_amount' => $totalAmount,
                    'status' => 'draft',
                ]);

                foreach ($itemsData as $item) {
                    $purchaseOrder->items()->create($item);
                }
            });

            return redirect()->back()->with('success', 'Purchase Order berhasil dibuat sebagai Draft.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function update(Request $request, PurchaseOrder $purchaseOrder): RedirectResponse
    {
        if ($purchaseOrder->status !== 'draft') {
            return redirect()->back()->with('error', 'Hanya Purchase Order berstatus Draft yang dapat diubah.');
        }

        $request->validate([
            'notes' => ['nullable', 'string'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.ingredient_id' => ['required', 'integer', 'exists:ingredients,id'],
            'items.*.qty' => ['required', 'numeric', 'min:0.0001'],
            'items.*.price' => ['required', 'numeric', 'min:0'],
        ]);

        try {
            DB::transaction(function () use ($request, $purchaseOrder) {
                $totalAmount = 0.0;
                
                // Delete old items
                $purchaseOrder->items()->delete();

                foreach ($request->items as $item) {
                    $subtotal = (float)$item['qty'] * (float)$item['price'];
                    $totalAmount += $subtotal;

                    $purchaseOrder->items()->create([
                        'ingredient_id' => (int)$item['ingredient_id'],
                        'qty' => (float)$item['qty'],
                        'price' => (float)$item['price'],
                        'subtotal' => $subtotal,
                    ]);
                }

                $purchaseOrder->update([
                    'notes' => $request->notes,
                    'total_amount' => $totalAmount,
                ]);
            });

            return redirect()->back()->with('success', 'Purchase Order berhasil diperbarui.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function destroy(PurchaseOrder $purchaseOrder): RedirectResponse
    {
        if (!in_array($purchaseOrder->status, ['draft', 'cancelled'])) {
            return redirect()->back()->with('error', 'Hanya PO Draft atau Batal yang dapat dihapus.');
        }

        $purchaseOrder->delete();
        return redirect()->back()->with('success', 'Purchase Order berhasil dihapus.');
    }

    public function send(PurchaseOrder $purchaseOrder): RedirectResponse
    {
        if ($purchaseOrder->status !== 'draft') {
            return redirect()->back()->with('error', 'Hanya PO Draft yang dapat dikirim.');
        }

        $purchaseOrder->update(['status' => 'sent']);
        return redirect()->back()->with('success', 'Purchase Order berhasil dikirim ke Pemasok.');
    }

    public function receive(Request $request, PurchaseOrder $purchaseOrder): RedirectResponse
    {
        if ($purchaseOrder->status !== 'sent') {
            return redirect()->back()->with('error', 'Hanya PO yang telah dikirim yang dapat diterima.');
        }

        try {
            DB::transaction(function () use ($request, $purchaseOrder) {
                $user = $request->user();

                // Transition status
                $purchaseOrder->update(['status' => 'received']);

                // Process Goods Received & Stock updates
                foreach ($purchaseOrder->items as $item) {
                    // Update or create outlet stock
                    $outletIngredient = OutletIngredient::firstOrCreate(
                        [
                            'outlet_id' => $purchaseOrder->outlet_id,
                            'ingredient_id' => $item->ingredient_id,
                        ],
                        [
                            'stock_qty' => 0,
                            'threshold_qty' => 5, // Default safety threshold
                        ]
                    );

                    $outletIngredient->increment('stock_qty', (float)$item->qty);

                    // Log audit trail transaction
                    StockTransaction::create([
                        'outlet_id' => $purchaseOrder->outlet_id,
                        'user_id' => $user->id,
                        'supplier_id' => $purchaseOrder->supplier_id,
                        'item_type' => 'Ingredient',
                        'item_id' => $item->ingredient_id,
                        'qty' => (float)$item->qty,
                        'type' => 'add',
                        'notes' => "Penerimaan barang dari PO {$purchaseOrder->po_number}",
                    ]);
                }
            });

            return redirect()->back()->with('success', 'Barang berhasil diterima. Stok bahan baku telah diperbarui!');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }
}
