<?php

namespace App\Services;

use App\Models\WarehouseStock;
use App\Models\WarehouseStockLog;
use Illuminate\Support\Facades\DB;
use RuntimeException;

class WarehouseDistributionService
{
    public function __construct(private readonly FranchiseStockService $franchiseStockService)
    {
    }

    /**
     * @param array<string, mixed> $context
     */
    public function dispatchToFranchise(
        int $warehouseId,
        int $franchiseId,
        int $productId,
        float $quantity,
        float $unitPrice,
        float $unitBv,
        array $context = []
    ): void {
        if ($quantity <= 0) {
            throw new RuntimeException('Dispatch quantity must be greater than zero.');
        }

        DB::transaction(function () use ($warehouseId, $franchiseId, $productId, $quantity, $unitPrice, $unitBv, $context): void {
            $warehouseStock = WarehouseStock::query()
                ->where('warehouse_id', $warehouseId)
                ->where('product_id', $productId)
                ->lockForUpdate()
                ->first();

            if (! $warehouseStock) {
                throw new RuntimeException('Warehouse stock not found for selected product.');
            }

            $opening = (float) $warehouseStock->quantity;
            if ($opening < $quantity) {
                throw new RuntimeException('Insufficient warehouse stock.');
            }

            $closing = round($opening - $quantity, 4);
            $warehouseStock->quantity = $closing;
            $warehouseStock->save();

            WarehouseStockLog::query()->create([
                'warehouse_id' => $warehouseId,
                'franchise_id' => $franchiseId,
                'product_id' => $productId,
                'transaction_type' => 'dispatch_to_franchise',
                'quantity' => $quantity,
                'opening_qty' => $opening,
                'closing_qty' => $closing,
                'reference' => $context['reference'] ?? null,
                'meta' => $context === [] ? null : $context,
                'created_by' => $context['created_by'] ?? null,
                'transacted_at' => now(),
            ]);

            $this->franchiseStockService->addStock(
                $franchiseId,
                $productId,
                $quantity,
                $unitPrice,
                $unitBv,
                'stock_in',
                $context
            );
        });
    }
}
