<?php

namespace App\Services;

use App\Models\Product;
use App\Models\StockLevel;
use App\Models\StockMovement;
use App\Models\User;
use Illuminate\Validation\ValidationException;

class InventoryService
{
    public function adjust(
        User $user,
        int $branchId,
        Product $product,
        ?int $variantId,
        float $quantityDelta,
        string $type,
        ?float $unitCost = null,
        ?int $batchId = null,
        ?string $referenceType = null,
        ?int $referenceId = null,
        ?string $notes = null,
        ?string $deviceId = null,
    ): StockLevel {
        $stock = StockLevel::firstOrCreate(
            [
                'branch_id' => $branchId,
                'product_id' => $product->id,
                'variant_id' => $variantId,
            ],
            [
                'quantity' => 0,
                'reserved_quantity' => 0,
            ]
        );

        $before = (float) $stock->quantity;
        $after = $before + $quantityDelta;

        if ($product->track_stock && ! $product->allow_negative_stock && $after < 0) {
            throw ValidationException::withMessages([
                'items' => ["Insufficient stock for {$product->name}."],
            ]);
        }

        $stock->forceFill(['quantity' => $after])->save();

        StockMovement::create([
            'branch_id' => $branchId,
            'product_id' => $product->id,
            'variant_id' => $variantId,
            'batch_id' => $batchId,
            'user_id' => $user->id,
            'type' => $type,
            'quantity' => $quantityDelta,
            'quantity_before' => $before,
            'quantity_after' => $after,
            'unit_cost' => $unitCost,
            'reference_type' => $referenceType,
            'reference_id' => $referenceId,
            'notes' => $notes,
            'device_id' => $deviceId,
        ]);

        return $stock->refresh();
    }
}
