<?php

namespace App\Domain\Applicants\Enums;

/**
 * High-level applicant state (§7). This is deliberately coarse: the detailed
 * journey lives in the configurable pipeline engine (§8, step 10), and this
 * enum only records whether a file is progressing, paused or finished.
 */
enum ApplicantStatus: string
{
    case Lead = 'lead';
    case Registered = 'registered';
    case InProcess = 'in_process';
    case OnHold = 'on_hold';
    case Deployed = 'deployed';
    case Completed = 'completed';
    case Withdrawn = 'withdrawn';
    case Rejected = 'rejected';
    case Cancelled = 'cancelled';
    case Blacklisted = 'blacklisted';
    case Merged = 'merged';

    public function label(): string
    {
        return match ($this) {
            self::Lead => 'Lead',
            self::Registered => 'Registered',
            self::InProcess => 'In Process',
            self::OnHold => 'On Hold',
            self::Deployed => 'Deployed',
            self::Completed => 'Completed',
            self::Withdrawn => 'Withdrawn',
            self::Rejected => 'Rejected',
            self::Cancelled => 'Cancelled',
            self::Blacklisted => 'Blacklisted',
            self::Merged => 'Merged',
        };
    }

    /** A closed file takes no further processing, payments or commission. */
    public function isClosed(): bool
    {
        return in_array($this, [
            self::Completed, self::Withdrawn, self::Rejected,
            self::Cancelled, self::Blacklisted, self::Merged,
        ], true);
    }

    public function isActive(): bool
    {
        return ! $this->isClosed();
    }

    public function requiresReason(): bool
    {
        return in_array($this, [
            self::OnHold, self::Withdrawn, self::Rejected, self::Cancelled, self::Blacklisted,
        ], true);
    }

    /** @return array<int, self> */
    public function allowedTransitions(): array
    {
        return match ($this) {
            self::Lead => [self::Registered, self::Withdrawn, self::Rejected, self::Cancelled],
            self::Registered => [self::InProcess, self::OnHold, self::Withdrawn, self::Rejected, self::Cancelled, self::Blacklisted],
            self::InProcess => [self::Deployed, self::OnHold, self::Withdrawn, self::Rejected, self::Cancelled, self::Blacklisted],
            self::OnHold => [self::InProcess, self::Withdrawn, self::Rejected, self::Cancelled, self::Blacklisted],
            self::Deployed => [self::Completed, self::OnHold],
            // A merged record is a tombstone; a closed file reopens only by decision.
            self::Merged => [],
            self::Completed, self::Withdrawn, self::Rejected, self::Cancelled => [self::InProcess],
            self::Blacklisted => [self::Registered],
        };
    }

    public function canTransitionTo(self $target): bool
    {
        return in_array($target, $this->allowedTransitions(), true);
    }

    /** @return array<int, string> */
    public static function values(): array
    {
        return array_column(self::cases(), 'value');
    }
}
