<?php

namespace CouponsPlus\App\Offers;

class HardLimit
{
    protected string $offerId;
    protected float $hardLimitAmount;
    protected float $usedAmount = 0.0;
    public function __construct(string $offerId, float $hardLimitAmount)
    {
        $this->offerId = $offerId;
        $this->hardLimitAmount = $hardLimitAmount;
    }

    public function getOfferId(): string
    {
        return $this->offerId;
    }

    public function getHardLimitAmount(): float
    {
        return $this->hardLimitAmount;
    }

    /**
     * Get the available amount that can still be used
     */
    public function getAvailableAmount(): float
    {
        $availableAmount = bcsub((string)$this->hardLimitAmount, (string)$this->usedAmount, 2);
        return max(0.0, (float)$availableAmount);
    }

    /**
     * Check if the hard limit has been reached
     */
    public function hasReachedHardLimit(): bool
    {
        return bccomp((string)$this->getAvailableAmount(), '0', 2) <= 0;
    }

    /**
     * Request an amount to use and update the available amount
     * Returns the actual amount that can be used (may be less than requested)
     */
    public function requestAndUpdateAvailableAmount(float $requestedAmount): float
    {
        $availableAmount = $this->getAvailableAmount();

        if (bccomp((string)$availableAmount, '0', 2) <= 0) {
            return 0.0;
        }

        $actualAmountToUse = bccomp((string)$requestedAmount, (string)$availableAmount, 2) <= 0
            ? $requestedAmount
            : $availableAmount;

        $this->usedAmount = (float)bcadd((string)$this->usedAmount, (string)$actualAmountToUse, 2);

        return $actualAmountToUse;
    }

    /**
     * Check if the whole discount amount can be used without side effects
     */
    public function canUseWholeDiscount(float $amount): bool
    {
        return bccomp((string)$amount, (string)$this->getAvailableAmount(), 2) <= 0;
    }
}