<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\Location;
use App\Models\Product;
use App\Models\PurchaseOrder;
use App\Models\Supplier;
use App\Services\LocationService;
use App\Services\PurchaseOrderService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PurchaseOrderController extends Controller
{
    public function __construct(
        protected PurchaseOrderService $purchaseOrders,
        protected LocationService $locationService
    ) {
        $this->middleware('auth');
    }

    public function index(Request $request): View
    {
        $user = auth()->user();
        $locations = $this->locationService->accessibleLocations($user);
        $accessibleIds = $locations->pluck('id')->all();
        $locationId = $this->locationService->resolveAuthorizedFilterLocationId($user, $request->input('location_id'));

        $orders = PurchaseOrder::query()
            ->with(['supplier', 'location'])
            ->withCount('items')
            ->when(!$this->locationService->userCanViewAllLocations($user), fn ($q) => $q->whereIn('location_id', $accessibleIds))
            ->when($locationId, fn ($q) => $q->where('location_id', $locationId))
            ->when($request->filled('status'), fn ($q) => $q->where('status', $request->status))
            ->when($request->filled('q'), function ($q) use ($request) {
                $term = '%' . $request->q . '%';
                $q->where(function ($q2) use ($term) {
                    $q2->where('po_number', 'like', $term)
                        ->orWhereHas('supplier', fn ($s) => $s->where('name', 'like', $term));
                });
            })
            ->latest()
            ->paginate(30);

        return view('admin.purchase-orders.index', compact('orders', 'locations', 'locationId'));
    }

    public function create(): View
    {
        $company = Company::primary() ?? $this->locationService->ensureCompanyAndDefaults();
        $suppliers = Supplier::query()->where('is_active', true)->orderBy('name')->get();
        $locations = $this->locationService->accessibleLocations(auth()->user());
        // Sellable stock rows only: single products + variant children (not variant parents)
        $products = Product::query()
            ->active()
            ->where(function ($q) {
                $q->where(function ($q2) {
                    $q2->whereNull('parent_id')->where('product_type', 'single');
                })->orWhereNotNull('parent_id');
            })
            ->orderBy('name')
            ->limit(1000)
            ->get(['id', 'name', 'sku', 'purchase_price', 'parent_id', 'product_type']);

        return view('admin.purchase-orders.create', compact('company', 'suppliers', 'locations', 'products'));
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'company_id' => 'required|exists:companies,id',
            'supplier_id' => 'required|exists:suppliers,id',
            'location_id' => 'required|exists:locations,id',
            'expected_date' => 'nullable|date',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.unit_cost' => 'required|numeric|min:0',
        ]);

        $this->locationService->resolveAuthorizedLocationId(auth()->user(), $data['location_id']);

        // Drop blank rows if user added extra empty lines
        $items = collect($data['items'])
            ->filter(fn ($item) => !empty($item['product_id']) && (int) ($item['quantity'] ?? 0) > 0)
            ->values()
            ->all();

        if (count($items) < 1) {
            return back()
                ->withInput()
                ->withErrors(['items' => 'Add at least one product with quantity. A single-product PO is allowed.']);
        }

        $po = $this->purchaseOrders->create($data, $items);

        return redirect()->route('admin.purchase-orders.show', $po)->with('success', 'Purchase order created.');
    }

    public function show(PurchaseOrder $purchase_order): View
    {
        $this->authorizePoAccess($purchase_order);
        $purchase_order->load(['supplier', 'location', 'items.product', 'goodsReceipts']);

        return view('admin.purchase-orders.show', ['po' => $purchase_order]);
    }

    public function markOrdered(PurchaseOrder $purchase_order): RedirectResponse
    {
        $this->authorizePoAccess($purchase_order);
        $this->purchaseOrders->markOrdered($purchase_order);

        return back()->with('success', 'PO marked as ordered.');
    }

    public function receive(Request $request, PurchaseOrder $purchase_order): RedirectResponse
    {
        $this->authorizePoAccess($purchase_order);
        $data = $request->validate([
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|integer|min:0',
            'notes' => 'nullable|string',
        ]);

        $receiveItems = collect($data['items'])->filter(fn ($i) => (int) $i['quantity'] > 0)->values()->all();
        $this->purchaseOrders->receive($purchase_order, $receiveItems, $data['notes'] ?? null);

        return back()->with('success', 'Goods receipt posted to warehouse/store inventory.');
    }

    protected function authorizePoAccess(PurchaseOrder $purchase_order): void
    {
        $user = auth()->user();
        if ($this->locationService->userCanViewAllLocations($user)) {
            return;
        }

        $this->locationService->resolveAuthorizedLocationId($user, $purchase_order->location_id);
    }
}
