import { ACHIEVEMENT_TITLE_CONFIG, AchievementTitleConfigItem, INFINITE_ACHIEVEMENT_TITLE } from '../config/AchievementTitleConfig';

export interface AchievementTitleInfo {
    readonly titleText: string;
    readonly nextTitleText: string;
    readonly nextTitleProgress: number;
    readonly progressText: string;
    readonly completedLevelCount: number;
    readonly currentTitleStartCount: number;
    readonly nextTitleRequiredCount: number;
    readonly remainingToNextTitle: number;
}

interface AchievementTitleStage {
    readonly titleText: string;
    readonly clearsToNext: number;
    readonly startCount: number;
}

export class AchievementTitleManager {
    public static getTitleInfo(completedLevelCount: number): AchievementTitleInfo {
        const safeCompletedCount = AchievementTitleManager.normalizeCompletedCount(completedLevelCount);
        const stages = AchievementTitleManager.buildFiniteStages();
        const finiteResult = AchievementTitleManager.findFiniteStage(safeCompletedCount, stages);

        if (finiteResult) {
            return AchievementTitleManager.createTitleInfo(safeCompletedCount, finiteResult.currentStage, finiteResult.nextStage);
        }

        return AchievementTitleManager.createInfiniteTitleInfo(safeCompletedCount, stages[stages.length - 1]);
    }

    private static normalizeCompletedCount(completedLevelCount: number): number {
        if (!Number.isFinite(completedLevelCount) || completedLevelCount < 0) {
            return 0;
        }

        return Math.floor(completedLevelCount);
    }

    private static buildFiniteStages(): AchievementTitleStage[] {
        let startCount = 0;

        return ACHIEVEMENT_TITLE_CONFIG.map((item: AchievementTitleConfigItem) => {
            const stage: AchievementTitleStage = {
                titleText: item.levelName,
                clearsToNext: item.clearsToNext,
                startCount
            };
            startCount += item.clearsToNext;
            return stage;
        });
    }

    private static findFiniteStage(completedLevelCount: number, stages: AchievementTitleStage[]): { currentStage: AchievementTitleStage; nextStage: AchievementTitleStage } | null {
        for (let index = 0; index < stages.length; index++) {
            const currentStage = stages[index];
            const nextStage = stages[index + 1] ?? {
                titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}1级`,
                clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
                startCount: currentStage.startCount + currentStage.clearsToNext
            };

            if (completedLevelCount < nextStage.startCount) {
                return { currentStage, nextStage };
            }
        }

        return null;
    }

    private static createInfiniteTitleInfo(completedLevelCount: number, lastFiniteStage: AchievementTitleStage): AchievementTitleInfo {
        const infiniteStartCount = lastFiniteStage.startCount + lastFiniteStage.clearsToNext;
        const completedAfterInfiniteStart = Math.max(0, completedLevelCount - infiniteStartCount);
        const currentInfiniteLevel = Math.floor(completedAfterInfiniteStart / INFINITE_ACHIEVEMENT_TITLE.clearsToNext) + 1;
        const currentStageStartCount = infiniteStartCount + (currentInfiniteLevel - 1) * INFINITE_ACHIEVEMENT_TITLE.clearsToNext;
        const nextStage: AchievementTitleStage = {
            titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}${currentInfiniteLevel + 1}级`,
            clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
            startCount: currentStageStartCount + INFINITE_ACHIEVEMENT_TITLE.clearsToNext
        };

        return AchievementTitleManager.createTitleInfo(
            completedLevelCount,
            {
                titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}${currentInfiniteLevel}级`,
                clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
                startCount: currentStageStartCount
            },
            nextStage
        );
    }

    private static createTitleInfo(completedLevelCount: number, currentStage: AchievementTitleStage, nextStage: AchievementTitleStage): AchievementTitleInfo {
        const interval = Math.max(1, nextStage.startCount - currentStage.startCount);
        const completedInCurrentTitle = Math.max(0, completedLevelCount - currentStage.startCount);
        const remainingToNextTitle = Math.max(0, nextStage.startCount - completedLevelCount);
        const nextTitleProgress = Math.max(0, Math.min(1, completedInCurrentTitle / interval));

        return {
            titleText: currentStage.titleText,
            nextTitleText: nextStage.titleText,
            nextTitleProgress,
            progressText: `还差${remainingToNextTitle}题获得${nextStage.titleText}`,
            completedLevelCount,
            currentTitleStartCount: currentStage.startCount,
            nextTitleRequiredCount: nextStage.startCount,
            remainingToNextTitle
        };
    }
}
