<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\FleetLoading;
use App\Models\Fleet;
use App\Models\Product;
use App\Models\Inventory;
use App\Models\StockMovement;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;

class FleetLoadingController extends Controller
{
    public function index()
    {
        $loadings = FleetLoading::with(['fleet', 'product'])->get();
        $fleets = Fleet::all();
        $products = Product::all();
        return view('fleet.loading', compact('loadings', 'fleets', 'products'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'fleet_id' => 'required|exists:fleets,id',
            'product_id' => 'required|exists:products,id',
            'load_type' => 'required|in:weight,quantity',
            'load_date' => 'required|date',
            'weight' => 'required_if:load_type,weight|nullable|numeric|min:0.01',
            'quantity' => 'required_if:load_type,quantity|nullable|numeric|min:1',
            'destination' => 'required',
        ]);

        return DB::transaction(function () use ($request) {
            $product = Product::findOrFail($request->product_id);
            $amountToLoad = $request->load_type == 'weight' ? $request->weight : $request->quantity;

            // Check total stock
            if ($product->totalStock() < $amountToLoad) {
                return redirect()->back()->withErrors(['amount' => 'Insufficient stock for this product. Available: ' . $product->totalStock()]);
            }

            // Deduct from inventories (simple logic: take from first available warehouse)
            $remainingToDeduct = $amountToLoad;
            $inventories = $product->inventories()->where('quantity', '>', 0)->get();

            foreach ($inventories as $inventory) {
                if ($remainingToDeduct <= 0) break;

                $deduction = min($inventory->quantity, $remainingToDeduct);
                $inventory->decrement('quantity', $deduction);
                $remainingToDeduct -= $deduction;

                // Record stock movement
                StockMovement::create([
                    'product_id' => $product->id,
                    'warehouse_id' => $inventory->warehouse_id,
                    'type' => 'out',
                    'quantity' => $deduction,
                    'reference_type' => 'FleetLoading',
                    'user_id' => Auth::id(),
                    'notes' => 'Dispatch (' . ucfirst($request->load_type) . ') to ' . $request->destination,
                ]);
            }

            $loading = FleetLoading::create([
                'fleet_id' => $request->fleet_id,
                'product_id' => $request->product_id,
                'load_type' => $request->load_type,
                'load_date' => $request->load_date,
                'cargo_type' => $product->name, 
                'weight' => $request->load_type == 'weight' ? $request->weight : null,
                'quantity' => $request->load_type == 'quantity' ? $request->quantity : null,
                'destination' => $request->destination,
                'status' => 'Pending',
            ]);

            // Update reference_id in stock movements
            StockMovement::where('product_id', $product->id)
                ->where('reference_type', 'FleetLoading')
                ->whereNull('reference_id')
                ->update(['reference_id' => $loading->id]);

            return redirect()->back()->with('success', 'Loading dispatch created and stock deducted.');
        });
    }

    public function update(Request $request, FleetLoading $loading)
    {
        $request->validate([
            'fleet_id' => 'required|exists:fleets,id',
            'product_id' => 'required|exists:products,id',
            'load_type' => 'required|in:weight,quantity',
            'load_date' => 'required|date',
            'weight' => 'required_if:load_type,weight|nullable|numeric|min:0.01',
            'quantity' => 'required_if:load_type,quantity|nullable|numeric|min:1',
            'destination' => 'required',
            'status' => 'required',
        ]);

        return DB::transaction(function () use ($request, $loading) {
            // 1. Restore old quantity to old product stockpile
            $oldProduct = $loading->product;
            $oldAmount = $loading->load_type == 'weight' ? $loading->weight : $loading->quantity;

            if ($oldProduct) {
                $inventory = $oldProduct->inventories()->first();
                if ($inventory) {
                    $inventory->increment('quantity', $oldAmount);
                    StockMovement::create([
                        'product_id' => $oldProduct->id,
                        'warehouse_id' => $inventory->warehouse_id,
                        'type' => 'in',
                        'quantity' => $oldAmount,
                        'reference_type' => 'FleetLoading',
                        'reference_id' => $loading->id,
                        'user_id' => Auth::id(),
                        'notes' => 'Stock adjustment (Correction/Edit ' . ucfirst($loading->load_type) . ')',
                    ]);
                }
            }

            // 2. Deduct new quantity from new product stockpile
            $newProduct = Product::findOrFail($request->product_id);
            $newAmount = $request->load_type == 'weight' ? $request->weight : $request->quantity;

            if ($newProduct->totalStock() < $newAmount) {
                throw new \Exception('Insufficient stock for the new selection.');
            }

            $remainingToDeduct = $newAmount;
            $inventories = $newProduct->inventories()->where('quantity', '>', 0)->get();

            foreach ($inventories as $inventory) {
                if ($remainingToDeduct <= 0) break;
                $deduction = min($inventory->quantity, $remainingToDeduct);
                $inventory->decrement('quantity', $deduction);
                $remainingToDeduct -= $deduction;

                StockMovement::create([
                    'product_id' => $newProduct->id,
                    'warehouse_id' => $inventory->warehouse_id,
                    'type' => 'out',
                    'quantity' => $deduction,
                    'reference_type' => 'FleetLoading',
                    'reference_id' => $loading->id,
                    'user_id' => Auth::id(),
                    'notes' => 'Updated Dispatch (' . ucfirst($request->load_type) . ') to ' . $request->destination,
                ]);
            }

            $loading->update([
                'fleet_id' => $request->fleet_id,
                'product_id' => $request->product_id,
                'load_type' => $request->load_type,
                'load_date' => $request->load_date,
                'cargo_type' => $newProduct->name,
                'weight' => $request->load_type == 'weight' ? $request->weight : null,
                'quantity' => $request->load_type == 'quantity' ? $request->quantity : null,
                'destination' => $request->destination,
                'status' => $request->status,
            ]);

            return redirect()->back()->with('success', 'Loading dispatch and stock adjusted successfully.');
        });
    }

    public function destroy(FleetLoading $loading)
    {
        return DB::transaction(function () use ($loading) {
            $product = $loading->product;
            $amountToRestore = $loading->load_type == 'weight' ? $loading->weight : $loading->quantity;

            if ($product) {
                $inventory = $product->inventories()->first();
                if ($inventory) {
                    $inventory->increment('quantity', $amountToRestore);
                    StockMovement::create([
                        'product_id' => $product->id,
                        'warehouse_id' => $inventory->warehouse_id,
                        'type' => 'in',
                        'quantity' => $amountToRestore,
                        'reference_type' => 'FleetLoading',
                        'reference_id' => $loading->id,
                        'user_id' => Auth::id(),
                        'notes' => 'Restoration after dispatch deletion (' . ucfirst($loading->load_type) . ')',
                    ]);
                }
            }

            $loading->delete();
            return redirect()->back()->with('success', 'Loading dispatch deleted and stock restored.');
        });
    }
}
