<?php

namespace App\Support;

use App\Enums\InvestmentStatus;
use App\Models\Investment;
use Carbon\Carbon;

final class InvestmentStatusHelper
{
    public static function isActive(Investment $investment): bool
    {
        return self::coerce($investment) === InvestmentStatus::Active;
    }

    public static function isCompleted(Investment $investment): bool
    {
        return self::coerce($investment) === InvestmentStatus::Completed;
    }

    public static function isCancelled(Investment $investment): bool
    {
        return self::coerce($investment) === InvestmentStatus::Cancelled;
    }

    public static function isActiveOrCompleted(Investment $investment): bool
    {
        return in_array(self::coerce($investment), [InvestmentStatus::Active, InvestmentStatus::Completed], true);
    }

    /**
     * Meses de contrato transcurridos (0 … duration_months), según confirmación y vencimiento.
     */
    public static function elapsedContractMonths(Investment $investment): int
    {
        if ($investment->confirmed_at === null) {
            return 0;
        }

        if (! self::isActiveOrCompleted($investment) && self::coerce($investment) !== InvestmentStatus::Pending) {
            return min(
                (int) $investment->duration_months,
                max(0, (int) $investment->months_credited),
            );
        }

        if (self::coerce($investment) === InvestmentStatus::Pending) {
            return 0;
        }

        $end = Carbon::now();
        if ($investment->maturity_at !== null) {
            $cap = $investment->maturity_at->copy()->subSecond();
            if ($cap->lt($end)) {
                $end = $cap;
            }
        }

        if ($end->lt($investment->confirmed_at)) {
            return 0;
        }

        return min(
            (int) $investment->duration_months,
            max(0, (int) $investment->confirmed_at->diffInMonths($end)),
        );
    }

    public static function isContractEnded(Investment $investment): bool
    {
        if ($investment->confirmed_at === null) {
            return false;
        }

        if ($investment->maturity_at !== null && now()->greaterThanOrEqualTo($investment->maturity_at)) {
            return true;
        }

        return self::elapsedContractMonths($investment) >= (int) $investment->duration_months;
    }

    /**
     * Alinea valores string / enum cuando el modelo se hidrata con subset de columnas.
     */
    public static function coerce(Investment $investment): InvestmentStatus
    {
        $status = $investment->status;

        if ($status instanceof InvestmentStatus) {
            return $status;
        }

        return InvestmentStatus::tryFrom((string) $status) ?? InvestmentStatus::Pending;
    }
}
