<?php

namespace App\Modules\Sales\Services;

use App\Modules\Inventory\Reservation\Repositories\InventoryReservationMovementRepository;
use App\Modules\Inventory\Stock\Support\DecimalQuantity;
use App\Modules\Sales\Exceptions\SalesOperationalException;
use App\Modules\Sales\Models\SalesOrder;
use App\Modules\Sales\Models\SalesOrderLine;

final class SalesFulfillmentLedgerGuard
{
    public function __construct(
        private readonly InventoryReservationMovementRepository $movements,
        private readonly SalesOperationalObservability $obs,
    ) {}

    public function assertOpenMatchesLine(
        int $tenantId,
        SalesOrder $order,
        SalesOrderLine $line,
        string $rid,
        ?string $correlationId,
    ): void {
        $open = $this->movements->sumOpenQuantity($tenantId, $rid);
        $lineReserved = trim((string) $line->quantity_reserved);
        if (DecimalQuantity::equals($open, $lineReserved)) {
            return;
        }
        $this->obs->reservationLeakageSignal(SalesOutboundEventContext::orderLine($tenantId, $order, $line, $correlationId) + [
            'ledger_open' => $open,
            'line_quantity_reserved' => $lineReserved,
        ]);
        throw new SalesOperationalException('Reservation ledger drift.', 'sales_reservation_drift');
    }
}
