<?php

namespace App\Livewire\Inventory;

use App\Domain\Inventory\Enums\MovementType;
use App\Domain\Inventory\Models\InventoryLevel;
use App\Domain\Inventory\Models\Product;
use App\Domain\Inventory\Models\Warehouse;
use App\Domain\Inventory\Services\InventoryService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('تسوية المخزون')]
class StockAdjustmentWizard extends Component
{
    use UsesBranchScope;

    public int $currentStep = 1;
    public int $totalSteps = 5;
    public bool $completed = false;

    // Step 1: Warehouse
    public ?int $warehouseId = null;

    // Step 2: Product
    public ?int $productId = null;

    // Step 3: Quantity & Reason
    public string $adjustmentDirection = 'up';
    public ?int $quantity = null;
    public string $reason = '';
    public ?string $referenceNumber = null;

    // Cached display data
    public ?array $selectedWarehouse = null;
    public ?array $selectedProduct = null;
    public ?int $currentStock = null;

    public function mount(): void
    {
        $this->authorize('inventory.adjust');
    }

    public function getStepLabels(): array
    {
        return [
            1 => 'المستودع',
            2 => 'المنتج',
            3 => 'الكمية والسبب',
            4 => 'مراجعة',
            5 => 'تأكيد',
        ];
    }

    public function selectWarehouse(int $id): void
    {
        $warehouse = Warehouse::findOrFail($id);
        $this->warehouseId = $id;
        $this->selectedWarehouse = [
            'id' => $warehouse->id,
            'name_ar' => $warehouse->name_ar,
            'name' => $warehouse->name,
        ];
        // Reset product selection when warehouse changes
        $this->productId = null;
        $this->selectedProduct = null;
        $this->currentStock = null;
    }

    public function selectProduct(int $id): void
    {
        $product = Product::findOrFail($id);
        $this->productId = $id;
        $this->selectedProduct = [
            'id' => $product->id,
            'name_ar' => $product->name_ar,
            'name' => $product->name,
            'sku' => $product->sku,
        ];
        $this->loadCurrentStock();
    }

    public function updatedWarehouseId(): void
    {
        if ($this->warehouseId && $this->productId) {
            $this->loadCurrentStock();
        }
    }

    public function updatedProductId(): void
    {
        if ($this->warehouseId && $this->productId) {
            $this->loadCurrentStock();
        }
    }

    private function loadCurrentStock(): void
    {
        if (!$this->warehouseId || !$this->productId) {
            $this->currentStock = null;
            return;
        }

        $level = InventoryLevel::where('product_id', $this->productId)
            ->where('warehouse_id', $this->warehouseId)
            ->first();

        $this->currentStock = $level?->quantity_on_hand ?? 0;
    }

    public function getExpectedAfterProperty(): ?int
    {
        if ($this->currentStock === null || !$this->quantity) {
            return null;
        }

        if ($this->adjustmentDirection === 'up') {
            return $this->currentStock + $this->quantity;
        }

        return $this->currentStock - $this->quantity;
    }

    public function nextStep(): void
    {
        $this->validate($this->rulesForStep($this->currentStep));

        if ($this->currentStep < $this->totalSteps) {
            $this->currentStep++;
        }
    }

    public function previousStep(): void
    {
        if ($this->currentStep > 1) {
            $this->currentStep--;
        }
    }

    public function goToStep(int $step): void
    {
        if ($step < $this->currentStep) {
            $this->currentStep = $step;
        }
    }

    public function confirm(): void
    {
        try {
            $product = Product::findOrFail($this->productId);
            $warehouse = Warehouse::findOrFail($this->warehouseId);

            $movementType = $this->adjustmentDirection === 'up'
                ? MovementType::CountAdjustmentUp
                : MovementType::CountAdjustmentDown;

            app(InventoryService::class)->createMovement(
                product: $product,
                warehouse: $warehouse,
                type: $movementType,
                quantity: $this->quantity,
                actor: auth()->user(),
                reason: $this->reason,
            );

            $this->completed = true;
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    private function rulesForStep(int $step): array
    {
        return match ($step) {
            1 => [
                'warehouseId' => 'required|integer|exists:warehouses,id',
            ],
            2 => [
                'productId' => 'required|integer|exists:products,id',
            ],
            3 => [
                'adjustmentDirection' => 'required|in:up,down',
                'quantity' => 'required|integer|min:1',
                'reason' => 'required|string|min:5|max:500',
                'referenceNumber' => 'nullable|string|max:100',
            ],
            default => [],
        };
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();
        $warehouses = Warehouse::active()
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->orderBy('name_ar')->get(['id', 'name_ar', 'name', 'code']);

        $products = collect();
        if ($this->warehouseId) {
            $products = Product::active()->tracked()->orderBy('name_ar')->get(['id', 'name_ar', 'name', 'sku']);
        }

        return view('livewire.inventory.stock-adjustment-wizard', [
            'warehouses' => $warehouses,
            'products' => $products,
        ]);
    }
}
