<?php

namespace App\Services\Recruitment;

use App\Models\Applicant;

class ReferralProgressService
{
    /** @var list<string> */
    public const PIPELINE_STAGES = ['applied', 'screening', 'interview', 'offer'];

    /**
     * @return array{
     *     stage: string,
     *     staff_label: string,
     *     percent: int,
     *     is_terminal: bool,
     *     is_positive_terminal: bool,
     *     steps: list<array{key: string, label: string, state: string}>
     * }
     */
    public function build(Applicant $applicant): array
    {
        $stage = (string) ($applicant->stage ?? 'applied');
        $isRejected = $stage === 'rejected';
        $steps = [];
        $currentIndex = $this->stageIndex($stage);

        foreach (self::PIPELINE_STAGES as $index => $key) {
            $state = 'upcoming';
            if ($isRejected) {
                $state = $index < $currentIndex || ($currentIndex < 0 && $index === 0) ? 'complete' : 'upcoming';
            } elseif ($index < $currentIndex) {
                $state = 'complete';
            } elseif ($index === $currentIndex) {
                $state = 'current';
            }

            $steps[] = [
                'key' => $key,
                'label' => $this->staffStepLabel($key),
                'state' => $state,
            ];
        }

        if ($isRejected) {
            $steps[] = [
                'key' => 'rejected',
                'label' => 'Not selected',
                'state' => 'terminal-negative',
            ];
        } elseif ($stage === 'offer') {
            $steps[count($steps) - 1]['state'] = 'terminal-positive';
        }

        return [
            'stage' => $stage,
            'staff_label' => $this->staffLabel($stage),
            'percent' => $this->percentComplete($stage),
            'is_terminal' => in_array($stage, ['rejected', 'offer'], true),
            'is_positive_terminal' => $stage === 'offer',
            'steps' => $steps,
        ];
    }

    public function staffLabel(string $stage): string
    {
        return match ($stage) {
            'applied' => 'Submitted — awaiting review',
            'screening' => 'Profile under review',
            'interview' => 'Interview in progress',
            'offer' => 'Offer stage',
            'rejected' => 'Not selected',
            default => ucfirst($stage),
        };
    }

    protected function staffStepLabel(string $stage): string
    {
        return match ($stage) {
            'applied' => 'Applied',
            'screening' => 'Screening',
            'interview' => 'Interview',
            'offer' => 'Offer',
            default => ucfirst($stage),
        };
    }

    protected function stageIndex(string $stage): int
    {
        $index = array_search($stage, self::PIPELINE_STAGES, true);

        return $index === false ? -1 : (int) $index;
    }

    protected function percentComplete(string $stage): int
    {
        if ($stage === 'rejected') {
            return 100;
        }

        $index = $this->stageIndex($stage);
        if ($index < 0) {
            return 0;
        }

        $total = count(self::PIPELINE_STAGES);

        return (int) round((($index + 1) / $total) * 100);
    }
}
