<?php

namespace App\Modules\Sales\Services;

use App\Modules\Inventory\Stock\Support\DecimalQuantity;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

final class SalesOrderUiBatchOperationService
{
    public function __construct(
        private readonly SalesReservationService $reservation,
        private readonly SalesFulfillmentService $fulfillment,
    ) {}

    /**
     * @param  list<array{line_id:int, quantity:string}>  $rows
     */
    public function allocateLines(
        int $tenantId,
        int $salesOrderId,
        array $rows,
        string $operationBatch,
        ?int $actorUserId,
    ): void {
        $cid = (string) Str::uuid();
        $attempts = (int) config('inventory.transaction_attempts', 5);
        DB::transaction(function () use ($tenantId, $salesOrderId, $rows, $operationBatch, $actorUserId, $cid): void {
            foreach ($rows as $row) {
                $qty = trim((string) ($row['quantity'] ?? ''));
                if ($qty === '' || ! DecimalQuantity::gtZero($qty)) {
                    continue;
                }
                $lineId = (int) $row['line_id'];
                $idem = 'ui-alloc-b'.$operationBatch.'-l'.$lineId;
                $this->reservation->allocateLineQuantity(
                    $tenantId,
                    $salesOrderId,
                    $lineId,
                    $qty,
                    $idem,
                    $cid,
                    $actorUserId,
                );
            }
        }, $attempts);
    }

    /**
     * @param  list<array{line_id:int, quantity:string}>  $rows
     */
    public function fulfillLines(
        int $tenantId,
        int $salesOrderId,
        array $rows,
        string $operationBatch,
        ?int $actorUserId,
    ): void {
        $cid = (string) Str::uuid();
        $attempts = (int) config('inventory.transaction_attempts', 5);
        DB::transaction(function () use ($tenantId, $salesOrderId, $rows, $operationBatch, $actorUserId, $cid): void {
            foreach ($rows as $row) {
                $qty = trim((string) ($row['quantity'] ?? ''));
                if ($qty === '' || ! DecimalQuantity::gtZero($qty)) {
                    continue;
                }
                $lineId = (int) $row['line_id'];
                $idem = 'ui-fulfill-b'.$operationBatch.'-l'.$lineId;
                $this->fulfillment->fulfillLineQuantity(
                    $tenantId,
                    $salesOrderId,
                    $lineId,
                    $qty,
                    $idem,
                    $cid,
                    $actorUserId,
                );
            }
        }, $attempts);
    }
}
