<?php

namespace App\Modules\Sales\Services;

use App\Modules\Inventory\Stock\Support\DecimalQuantity;
use App\Modules\Sales\Exceptions\SalesReturnOperationalException;
use App\Modules\Sales\Models\SalesOrder;
use App\Modules\Sales\Models\SalesOrderLine;
use App\Modules\Sales\Models\SalesReturn;
use App\Modules\Sales\Repositories\SalesReturnLineQuantityRepository;
use App\Modules\Sales\Support\SalesOrderLifecycleStatus;
use App\Modules\Sales\Support\SalesReturnStatus;

final class SalesReturnValidationService
{
    public function __construct(
        private readonly SalesReturnLineQuantityRepository $returnedQty,
    ) {}

    public function assertOrderAllowsReturns(SalesOrder $order): void
    {
        if (SalesOrderLifecycleStatus::tryFrom((string) $order->status) === SalesOrderLifecycleStatus::Cancelled) {
            throw new SalesReturnOperationalException('Cancelled orders cannot process returns.', 'sales_return_order_cancelled');
        }
    }

    public function assertLineQuantity(
        int $tenantId,
        SalesOrderLine $line,
        string $quantity,
        ?int $excludeReturnId,
    ): void {
        $qty = trim($quantity);
        if (! DecimalQuantity::gtZero($qty)) {
            throw new SalesReturnOperationalException('Return quantity must be positive.', 'sales_return_qty_invalid');
        }
        $fulfilled = trim((string) $line->quantity_fulfilled);
        $already = $this->returnedQty->sumProcessedQuantityForOrderLine($tenantId, (int) $line->id, $excludeReturnId);
        $cap = DecimalQuantity::add($fulfilled, DecimalQuantity::negate($already));
        if (DecimalQuantity::gte($cap, $qty)) {
            return;
        }
        throw new SalesReturnOperationalException('Return exceeds fulfilled quantity.', 'sales_return_over_return');
    }

    public function assertReturnReadyToProcess(SalesReturn $return): void
    {
        if ($return->status !== SalesReturnStatus::Received->value) {
            throw new SalesReturnOperationalException('Return must be received before processing.', 'sales_return_wrong_status');
        }
    }
}
