<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\GenerateAuditAdjustmentsRequest;
use App\Http\Requests\Admin\LoadAuditProductsRequest;
use App\Http\Requests\Admin\StoreStockAuditRequest;
use App\Http\Requests\Admin\UpdatePhysicalQtyRequest;
use App\Models\Category;
use App\Models\Location;
use App\Models\Product;
use App\Models\StockAdjustment;
use App\Models\StockAudit;
use App\Services\LocationService;
use App\Services\StockAuditService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class StockAuditController extends Controller
{
    public function __construct(
        protected StockAuditService $stockAuditService,
        protected LocationService $locationService
    ) {}

    public function index(Request $request): View
    {
        $this->authorize('stock-audit.view');
        $user = auth()->user();
        $locations = $this->locationService->accessibleLocations($user);
        $accessibleIds = $locations->pluck('id')->all();
        $locationId = $this->locationService->resolveAuthorizedFilterLocationId($user, $request->input('location_id'));

        $query = StockAudit::with(['creator', 'location'])->latest('audit_date');
        if (!$this->locationService->userCanViewAllLocations($user)) {
            $query->whereIn('location_id', $accessibleIds);
        }
        if ($request->filled('status') && in_array($request->status, ['draft', 'completed'])) {
            $query->where('status', $request->status);
        }
        if ($locationId) {
            $query->where('location_id', $locationId);
        }
        $audits = $query->paginate(20);
        return view('admin.stock-audit.index', compact('audits', 'locations', 'locationId'));
    }

    public function create(): View
    {
        $this->authorize('stock-audit.create');
        $locations = $this->locationService->accessibleLocations(auth()->user());
        return view('admin.stock-audit.create', compact('locations'));
    }

    public function store(StoreStockAuditRequest $request): RedirectResponse
    {
        $this->authorize('stock-audit.create');
        $data = $request->validated();
        $this->locationService->resolveAuthorizedLocationId(auth()->user(), $data['location_id'] ?? null);
        $audit = $this->stockAuditService->createAudit($data);
        return redirect()->route('admin.stock-audit.load-products', $audit)
            ->with('success', 'Audit created. Load products to continue.');
    }

    public function loadProducts(StockAudit $stock_audit): View|RedirectResponse
    {
        $this->authorize('stock-audit.create');
        if ($stock_audit->location_id) {
            $this->locationService->resolveAuthorizedLocationId(auth()->user(), $stock_audit->location_id);
        }

        if ($stock_audit->isCompleted()) {
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('error', 'Cannot load products into a completed audit.');
        }
        $categories = Category::orderBy('name')->get();
        return view('admin.stock-audit.load-products', compact('stock_audit', 'categories'));
    }

    public function storeLoadProducts(LoadAuditProductsRequest $request, StockAudit $stock_audit): RedirectResponse
    {
        $this->authorize('stock-audit.create');

        if ($stock_audit->isCompleted()) {
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('error', 'Cannot load products into a completed audit.');
        }
        try {
            $data = $request->validated();
            $scope = $data['scope'];
            $categoryIds = $scope === 'category' ? ($data['category_ids'] ?? []) : null;
            $productIds = $scope === 'skus' ? ($data['product_ids'] ?? []) : null;
            $this->stockAuditService->loadProductsIntoAudit($stock_audit, $scope, $categoryIds, $productIds);
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('success', 'Products loaded. Enter physical counts.');
        } catch (\Exception $e) {
            return redirect()->back()->withInput()->with('error', $e->getMessage());
        }
    }

    public function show(StockAudit $stock_audit): View|RedirectResponse
    {
        abort_unless(
            auth()->user()?->canAny(['stock-audit.view', 'stock-audit.create']),
            403,
            'You do not have permission to view stock audits.'
        );

        if ($stock_audit->location_id) {
            $this->locationService->resolveAuthorizedLocationId(auth()->user(), $stock_audit->location_id);
        }

        $stock_audit->load(['items.product', 'items.variant', 'creator']);
        return view('admin.stock-audit.show', compact('stock_audit'));
    }

    public function updatePhysicalQty(UpdatePhysicalQtyRequest $request, StockAudit $stock_audit): RedirectResponse
    {
        $this->authorize('stock-audit.create');

        if ($stock_audit->isCompleted()) {
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('error', 'Cannot update a completed audit.');
        }
        try {
            $this->stockAuditService->updatePhysicalQuantities($stock_audit, $request->validated('items', []));
            return redirect()->back()->with('success', 'Physical quantities updated.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function generateAdjustments(GenerateAuditAdjustmentsRequest $request, StockAudit $stock_audit): RedirectResponse
    {
        $this->authorize('stock-audit.create');
        if ($stock_audit->isCompleted()) {
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('error', 'Audit is already completed.');
        }
        if (StockAdjustment::where('reference_type', StockAdjustment::REFERENCE_AUDIT)->where('reference_id', $stock_audit->id)->exists()) {
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('error', 'Adjustments have already been generated for this audit.');
        }
        try {
            $this->stockAuditService->generateAndApplyAdjustments($stock_audit, $request->validated('remarks'));
            return redirect()->route('admin.stock-audit.show', $stock_audit)
                ->with('success', 'Adjustments generated and stock updated.');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', $e->getMessage());
        }
    }
}
