<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreRestockRequest;
use App\Http\Requests\Admin\StoreVariantRestockRequest;
use App\Models\InventoryBalance;
use App\Models\Product;
use App\Models\StockMovement;
use App\Models\VariantStockMovement;
use App\Services\LocationInventoryService;
use App\Services\LocationService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\View\View;

class RestockController extends Controller
{
    public function __construct(
        protected LocationInventoryService $locationInventory,
        protected LocationService $locationService
    ) {
    }

    public function index(Request $request): View
    {
        $this->authorize('products.restock');

        $user = auth()->user();
        $locations = $this->locationService->restockWarehouseLocations($user);

        $locationId = $this->locationService->resolveWarehouseRestockLocationId(
            $user,
            $request->input('location_id')
        );

        $products = Product::with('stockMovements')
            ->where('product_type', 'single')
            ->orderBy('name')
            ->get();

        $balancesByProduct = collect();
        if ($locationId && Schema::hasTable('inventory_balances')) {
            $balancesByProduct = InventoryBalance::query()
                ->where('location_id', $locationId)
                ->whereIn('product_id', $products->pluck('id'))
                ->get()
                ->keyBy('product_id');
        }

        $products->each(function ($product) use ($locationId, $balancesByProduct) {
            if ($locationId && $this->locationInventory->useLocationInventory()) {
                $balance = $balancesByProduct->get($product->id);
                $product->calculated_current_stock = $balance
                    ? max(0, (int) $balance->on_hand - (int) $balance->reserved - (int) ($balance->damaged ?? 0))
                    : 0;
            } else {
                $product->calculated_current_stock = $product->stockMovements->sum('quantity');
            }
        });

        return view('admin.products.restock', compact('products', 'locations', 'locationId'));
    }

    public function store(StoreRestockRequest $request): RedirectResponse
    {
        $data = $request->validated();

        try {
            DB::beginTransaction();

            $product = Product::findOrFail($data['product_id']);
            $locationId = $this->locationService->resolveWarehouseRestockLocationId(
                auth()->user(),
                $data['location_id'] ?? null
            );

            if ($this->locationInventory->useLocationInventory()) {
                $this->locationInventory->restock(
                    (int) $product->id,
                    (int) $data['quantity'],
                    $locationId,
                    $data['notes'] ?? null,
                    auth()->id()
                );
                $currentStock = $this->locationInventory->getOnHand((int) $product->id, $locationId);
            } else {
                StockMovement::create([
                    'product_id' => $product->id,
                    'type' => StockMovement::TYPE_RESTOCK,
                    'quantity' => $data['quantity'],
                    'notes' => $data['notes'] ?? null,
                    'created_by' => auth()->id(),
                ]);
                $product->recalculateStock();
                $currentStock = $product->stockMovements()->sum('quantity');
            }

            DB::commit();

            return redirect()->route('admin.products.restock', ['location_id' => $locationId])
                ->with('success', "Stock restocked at warehouse successfully! Current warehouse stock: {$currentStock}");
        } catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) {
            DB::rollBack();

            return redirect()->route('admin.products.restock')
                ->with('error', $e->getMessage());
        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->route('admin.products.restock')
                ->with('error', 'Failed to restock: ' . $e->getMessage());
        }
    }

    /**
     * Restock a product variant (now a Product with parent_id)
     */
    public function storeVariant(StoreVariantRestockRequest $request, Product $variant): RedirectResponse
    {
        if (is_null($variant->parent_id)) {
            return redirect()->route('admin.products.index')
                ->with('error', 'This is not a variant product.');
        }

        $data = $request->validated();

        try {
            DB::beginTransaction();

            $locationId = $this->locationService->resolveWarehouseRestockLocationId(
                auth()->user(),
                $data['location_id'] ?? null
            );

            if ($this->locationInventory->useLocationInventory()) {
                $this->locationInventory->restock(
                    (int) $variant->id,
                    (int) $data['quantity'],
                    $locationId,
                    $data['notes'] ?? null,
                    auth()->id()
                );
                $variant->refresh();
                $currentStock = $this->locationInventory->getOnHand((int) $variant->id, $locationId);
            } else {
                VariantStockMovement::create([
                    'product_id' => $variant->id,
                    'type' => VariantStockMovement::TYPE_RESTOCK,
                    'quantity' => $data['quantity'],
                    'notes' => $data['notes'] ?? null,
                    'created_by' => auth()->id(),
                ]);
                $variant->recalculateStock();
                $variant->refresh();
                $currentStock = $variant->current_stock;
            }

            DB::commit();

            if ($request->has('return_to_list') && $request->return_to_list == '1') {
                $redirectUrl = route('admin.products.index', ['type' => 'variant']);
                if ($request->has('search') && $request->search) {
                    $redirectUrl .= '&search=' . urlencode($request->search);
                }

                return redirect($redirectUrl)
                    ->with('success', "Variant restocked at warehouse successfully! Current warehouse stock: {$currentStock}");
            }

            return redirect()->route('admin.products.variants.index', $variant->parent_id)
                ->with('success', "Variant restocked at warehouse successfully! Current warehouse stock: {$currentStock}");
        } catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) {
            DB::rollBack();

            return $this->variantRestockErrorRedirect($request, $variant, $e->getMessage());
        } catch (\Exception $e) {
            DB::rollBack();

            return $this->variantRestockErrorRedirect($request, $variant, 'Failed to restock variant: ' . $e->getMessage());
        }
    }

    protected function variantRestockErrorRedirect(Request $request, Product $variant, string $message): RedirectResponse
    {
        if ($request->has('return_to_list') && $request->return_to_list == '1') {
            $redirectUrl = route('admin.products.index', ['type' => 'variant']);
            if ($request->has('search') && $request->search) {
                $redirectUrl .= '&search=' . urlencode($request->search);
            }

            return redirect($redirectUrl)->with('error', $message);
        }

        return redirect()->route('admin.products.variants.index', $variant->parent_id)
            ->with('error', $message);
    }
}
