import { stageOptions } from "@/features/lucky-gift/constants.js";
import {
    applyProbabilityMap,
    correctRTPProbabilities,
    decimal,
    expectedRTPPercent,
    formatDecimal,
    probabilityTotal,
    tierRTPContributionPercent,
} from "@/shared/utils/rtpProbability.js";

export const luckyGiftReferenceCost = 100;

const defaultStageTiers = {
    novice: [
        tier("novice_none", 0, 10),
        tier("novice_0_5x", 0.5, 20),
        tier("novice_1x", 1, 55),
        tier("novice_2x", 2, 15),
    ],
    normal: [
        tier("normal_none", 0, 10),
        tier("normal_0_5x", 0.5, 20),
        tier("normal_1x", 1, 55),
        tier("normal_2x", 2, 15),
    ],
    advanced: [
        tier("advanced_none", 0, 27),
        tier("advanced_1x", 1, 60),
        tier("advanced_2x", 2, 10),
        tier("advanced_5x", 5, 3, { highWaterOnly: true, broadcastLevel: "room" }),
    ],
};

export function emptyLuckyGiftForm() {
    return {
        controlBandPercent: "1",
        effectiveFromMs: "0",
        enabled: false,
        giftPriceReference: String(luckyGiftReferenceCost),
        noviceMaxEquivalentDraws: "2000",
        normalMaxEquivalentDraws: "20000",
        maxSinglePayout: "50000",
        userHourlyPayoutCap: "34200",
        userDailyPayoutCap: "615600",
        deviceDailyPayoutCap: "1026000",
        roomHourlyPayoutCap: "684000",
        anchorDailyPayoutCap: "12312000",
        poolId: "default",
        poolRatePercent: "96",
        settlementWindowWager: "1000000",
        stages: cloneStages(defaultStages()),
        targetRtpPercent: "95",
    };
}

export function formFromConfig(config) {
    if (!config) {
        return emptyLuckyGiftForm();
    }
    const fallback = emptyLuckyGiftForm();
    return {
        controlBandPercent: formatDecimal(config.controlBandPercent || fallback.controlBandPercent),
        effectiveFromMs: String(config.effectiveFromMs || 0),
        enabled: Boolean(config.enabled),
        giftPriceReference: String(config.giftPriceReference || fallback.giftPriceReference),
        noviceMaxEquivalentDraws: String(config.noviceMaxEquivalentDraws || fallback.noviceMaxEquivalentDraws),
        normalMaxEquivalentDraws: String(config.normalMaxEquivalentDraws || fallback.normalMaxEquivalentDraws),
        maxSinglePayout: String(config.maxSinglePayout || fallback.maxSinglePayout),
        userHourlyPayoutCap: String(config.userHourlyPayoutCap || fallback.userHourlyPayoutCap),
        userDailyPayoutCap: String(config.userDailyPayoutCap || fallback.userDailyPayoutCap),
        deviceDailyPayoutCap: String(config.deviceDailyPayoutCap || fallback.deviceDailyPayoutCap),
        roomHourlyPayoutCap: String(config.roomHourlyPayoutCap || fallback.roomHourlyPayoutCap),
        anchorDailyPayoutCap: String(config.anchorDailyPayoutCap || fallback.anchorDailyPayoutCap),
        poolId: config.poolId || "default",
        poolRatePercent: formatDecimal(config.poolRatePercent || fallback.poolRatePercent),
        settlementWindowWager: String(config.settlementWindowWager || fallback.settlementWindowWager),
        stages: normalizeStages(config.stages),
        targetRtpPercent: formatDecimal(config.targetRTPPercent || fallback.targetRtpPercent),
    };
}

export function payloadFromLuckyGiftForm(form) {
    // 第一阶段的新契约明确要求后台只提交百分比和倍数；ppm 是 server 的持久化细节，
    // 这里保留业务单位可以避免再次出现 target_rtp_ppm=95 这类单位错配。
    const stages = assignGeneratedTierIDs(normalizeStages(form.stages));
    return {
        control_band_percent: decimal(form.controlBandPercent),
        effective_from_ms: integer(form.effectiveFromMs),
        enabled: Boolean(form.enabled),
        gift_price_reference: integer(form.giftPriceReference),
        novice_max_equivalent_draws: integer(form.noviceMaxEquivalentDraws),
        normal_max_equivalent_draws: integer(form.normalMaxEquivalentDraws),
        max_single_payout: integer(form.maxSinglePayout),
        user_hourly_payout_cap: integer(form.userHourlyPayoutCap),
        user_daily_payout_cap: integer(form.userDailyPayoutCap),
        device_daily_payout_cap: integer(form.deviceDailyPayoutCap),
        room_hourly_payout_cap: integer(form.roomHourlyPayoutCap),
        anchor_daily_payout_cap: integer(form.anchorDailyPayoutCap),
        pool_id: String(form.poolId || "").trim(),
        pool_rate_percent: decimal(form.poolRatePercent),
        settlement_window_wager: integer(form.settlementWindowWager),
        stages: stages.map((stage) => ({
            stage: stage.stage,
            tiers: stage.tiers.map((item) => ({
                broadcast_level: item.broadcastLevel,
                enabled: Boolean(item.enabled),
                high_water_only: Boolean(item.highWaterOnly),
                multiplier: decimal(item.multiplier),
                probability_percent: decimal(item.probabilityPercent),
                reward_source: item.rewardSource,
                tier_id: String(item.tierId || "").trim(),
            })),
        })),
        target_rtp_percent: decimal(form.targetRtpPercent),
    };
}

export function previewForForm(form) {
    // 预览只用于管理员在保存前核对预算规模，不反推线上中奖概率；
    // 真实抽奖控制必须以 activity-service 发布后的规则版本为准。
    const spend = integer(form.giftPriceReference) * 100_000;
    const targetRTP = decimal(form.targetRtpPercent) / 100;
    const poolRate = decimal(form.poolRatePercent) / 100;
    const basePayout = Math.round(spend * targetRTP);
    const poolInflow = Math.round(spend * poolRate);
    return {
        basePayout,
        controlBandPercent: decimal(form.controlBandPercent),
        poolInflow,
        spend,
        targetRTPPercent: decimal(form.targetRtpPercent),
    };
}

export function addTierToStage(stages, stageKey) {
    return assignGeneratedTierIDs(
        stages.map((stage) => {
            if (stage.stage !== stageKey) {
                return stage;
            }
            const nextMultiplier = nextSuggestedTierMultiplier(stage.tiers);
            return {
                ...stage,
                tiers: [
                    ...stage.tiers,
                    tier(tierIDFromMultiplier(stage.stage, nextMultiplier), nextMultiplier, "", {
                        broadcastLevel: "none",
                        highWaterOnly: nextMultiplier >= 5,
                        rewardSource: "base_rtp",
                    }),
                ],
            };
        }),
    );
}

export function removeTierFromStage(stages, stageKey, tierIndex) {
    return stages.map((stage) => {
        if (stage.stage !== stageKey) {
            return stage;
        }
        return { ...stage, tiers: stage.tiers.filter((_, index) => index !== tierIndex) };
    });
}

export function updateStageTier(stages, stageKey, tierIndex, patch) {
    return stages.map((stage) => {
        if (stage.stage !== stageKey) {
            return stage;
        }
        return {
            ...stage,
            tiers: stage.tiers.map((item, index) => (index === tierIndex ? { ...item, ...patch } : item)),
        };
    });
}

export function correctStageTierProbabilities(stages, stageKey, targetRTPPercent) {
    return stages.map((stage) => {
        if (stage.stage !== stageKey) {
            return stage;
        }
        const probabilityByIndex = correctRTPProbabilities(stage.tiers, targetRTPPercent, {
            multiplier: (item) => item.multiplier,
            participatesInRTP: (item) => item.rewardSource === "base_rtp",
        });
        if (!probabilityByIndex) {
            return stage;
        }
        return {
            ...stage,
            tiers: applyProbabilityMap(stage.tiers, probabilityByIndex),
        };
    });
}

export function stageProbabilityTotal(stage) {
    // 与 activity-service 的发布校验保持同一口径：只有启用奖档参与 100% 概率闭合；
    // 禁用奖档只是草稿行，不能让前端显示通过但服务端按启用集合拒绝。
    return probabilityTotal(stage?.tiers || []);
}

export function stageExpectedRTP(stage) {
    // 阶段期望 RTP 是发布时真正校验的概率口径：只统计启用的基础 RTP 奖档，活动补贴和表现奖励不参与基础返奖率。
    return expectedRTPPercent(stage?.tiers || [], {
        multiplier: (item) => item.multiplier,
        participatesInRTP: (item) => item.rewardSource === "base_rtp",
    });
}

export function tierRTPContribution(tier) {
    return tierRTPContributionPercent(tier, {
        multiplier: (item) => item.multiplier,
        participatesInRTP: (item) => item.rewardSource === "base_rtp",
    });
}

export function assignGeneratedTierIDs(stages) {
    return (stages || []).map((stage) => {
        const used = new Map();
        const tiers = (stage.tiers || []).map((item) => {
            const baseID = tierIDFromMultiplier(stage.stage, item.multiplier);
            const usedCount = used.get(baseID) || 0;
            used.set(baseID, usedCount + 1);
            return {
                ...item,
                tierId: usedCount === 0 ? baseID : `${baseID}_${usedCount + 1}`,
            };
        });
        return { ...stage, tiers };
    });
}

function defaultStages() {
    return stageOptions.map(([stage]) => ({ stage, tiers: defaultStageTiers[stage].map((item) => ({ ...item })) }));
}

function nextSuggestedTierMultiplier(tiers) {
    const usedMultipliers = (tiers || [])
        .map((item) => decimal(item.multiplier))
        .filter((value) => Number.isFinite(value) && value > 0);
    if (usedMultipliers.length === 0) {
        return 1;
    }
    const maxMultiplier = Math.max(...usedMultipliers);
    if (maxMultiplier >= 5) {
        return maxMultiplier * 2;
    }
    if (maxMultiplier >= 2) {
        return 5;
    }
    return maxMultiplier + 1;
}

function tierIDFromMultiplier(stage, multiplier) {
    const value = decimal(multiplier);
    if (value <= 0) {
        return `${stage}_none`;
    }
    const multiplierText = formatDecimal(value).replace(".", "_");
    return `${stage}_${multiplierText}x`;
}

function normalizeStages(stages) {
    // server 返回缺阶段时仍用默认三阶段补齐表单，保证运营看到的是完整发布形态；
    // 保存时 schema 会再次校验概率合计和 0x 档，不让半成品配置进入发布请求。
    const byStage = new Map((stages || []).map((stage) => [stage.stage, stage]));
    return assignGeneratedTierIDs(
        stageOptions.map(([stage]) => {
            const source = byStage.get(stage);
            const tiers =
                Array.isArray(source?.tiers) && source.tiers.length > 0 ? source.tiers : defaultStageTiers[stage];
            return {
                stage,
                tiers: tiers.map((item) => ({
                    broadcastLevel: item.broadcastLevel || "none",
                    enabled: item.enabled !== false,
                    highWaterOnly: Boolean(item.highWaterOnly),
                    multiplier: formatDecimal(item.multiplier),
                    probabilityPercent: formatDecimal(item.probabilityPercent),
                    rewardSource: item.rewardSource || "base_rtp",
                    tierId: item.tierId || "",
                })),
            };
        }),
    );
}

function cloneStages(stages) {
    return stages.map((stage) => ({ ...stage, tiers: stage.tiers.map((item) => ({ ...item })) }));
}

function tier(tierId, multiplier, probabilityPercent, options = {}) {
    return {
        broadcastLevel: options.broadcastLevel || "none",
        enabled: options.enabled ?? true,
        highWaterOnly: Boolean(options.highWaterOnly),
        multiplier,
        probabilityPercent,
        rewardSource: options.rewardSource || "base_rtp",
        tierId,
    };
}

function integer(value) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? Math.round(number) : 0;
}
