import { z } from "zod";

const numberInput = z.union([z.string(), z.number()]);

const rewardSchema = z.object({
    displayName: z.string().optional(),
    iconUrl: z.string().optional(),
    quantity: numberInput,
    resourceGroupId: numberInput,
    rewardItemId: z.string().optional(),
    weight: numberInput,
});

const levelSchema = z.object({
    animationUrl: z.string().optional(),
    coverUrl: z.string().optional(),
    fuelThreshold: numberInput,
    igniterRewards: z.array(rewardSchema),
    inRoomRewards: z.array(rewardSchema),
    level: z.number().int().min(1).max(5),
    launchedImageUrl: z.string().optional(),
    launchAnimationUrl: z.string().optional(),
    top1Rewards: z.array(rewardSchema),
});

const giftFuelRuleSchema = z.object({
    excluded: z.boolean(),
    fixedFuel: numberInput,
    giftId: z.string().optional(),
    giftTypeCode: z.string().optional(),
    multiplierPpm: numberInput,
    ruleId: z.string().optional(),
});

export const roomRocketConfigFormSchema = z
    .object({
        broadcastDelayMs: numberInput,
        broadcastEnabled: z.boolean(),
        broadcastScope: z.enum(["none", "region", "global"]),
        enabled: z.boolean(),
        fuelSource: z.literal("heat_value"),
        giftFuelRules: z.array(giftFuelRuleSchema),
        levels: z.array(levelSchema).length(5, "必须配置 5 级火箭"),
        launchDelayMs: numberInput,
        rewardStackPolicy: z.enum(["allow_stack", "priority_only"]),
    })
    .superRefine((value, context) => {
        if (!validNonNegativeInteger(value.launchDelayMs)) {
            context.addIssue({ code: "custom", message: "发射倒计时必须大于等于 0", path: ["launchDelayMs"] });
        }
        if (!validNonNegativeInteger(value.broadcastDelayMs)) {
            context.addIssue({ code: "custom", message: "广播延迟必须大于等于 0", path: ["broadcastDelayMs"] });
        }

        const seen = new Set<number>();
        for (const level of value.levels) {
            if (seen.has(level.level)) {
                context.addIssue({ code: "custom", message: "火箭等级不能重复", path: ["levels"] });
            }
            seen.add(level.level);
            if (!positiveInteger(level.fuelThreshold)) {
                context.addIssue({
                    code: "custom",
                    message: `第 ${level.level} 级燃料阈值必须大于 0`,
                    path: ["levels", level.level - 1, "fuelThreshold"],
                });
            }
            validateRewards(context, level.level, "inRoomRewards", level.inRoomRewards);
            validateRewards(context, level.level, "top1Rewards", level.top1Rewards);
            validateRewards(context, level.level, "igniterRewards", level.igniterRewards);
        }

        value.giftFuelRules.forEach((rule, index) => {
            const giftId = String(rule.giftId || "").trim();
            const giftTypeCode = String(rule.giftTypeCode || "").trim();
            const multiplierPpm = Number(rule.multiplierPpm || 0);
            const fixedFuel = Number(rule.fixedFuel || 0);
            if (!giftId && !giftTypeCode) {
                context.addIssue({
                    code: "custom",
                    message: "礼物燃料规则必须填写礼物 ID 或礼物类型",
                    path: ["giftFuelRules", index, "giftId"],
                });
            }
            if (
                !Number.isInteger(multiplierPpm) ||
                multiplierPpm < 0 ||
                !Number.isInteger(fixedFuel) ||
                fixedFuel < 0
            ) {
                context.addIssue({
                    code: "custom",
                    message: "礼物燃料规则数值必须大于等于 0",
                    path: ["giftFuelRules", index, "multiplierPpm"],
                });
            }
            if (!rule.excluded && multiplierPpm === 0 && fixedFuel === 0) {
                context.addIssue({
                    code: "custom",
                    message: "非排除规则必须配置倍率或固定燃料",
                    path: ["giftFuelRules", index, "multiplierPpm"],
                });
            }
        });
    });

export type RoomRocketConfigForm = z.infer<typeof roomRocketConfigFormSchema>;

function validateRewards(
    context: z.RefinementCtx,
    level: number,
    key: string,
    rewards: z.infer<typeof rewardSchema>[],
) {
    rewards.forEach((reward, index) => {
        const empty =
            !Number(reward.resourceGroupId || 0) &&
            !Number(reward.weight || 0) &&
            !Number(reward.quantity || 0) &&
            !String(reward.displayName || "").trim() &&
            !String(reward.iconUrl || "").trim();
        if (empty) {
            return;
        }
        if (!positiveInteger(reward.resourceGroupId)) {
            context.addIssue({
                code: "custom",
                message: `第 ${level} 级奖励必须选择资源组`,
                path: ["levels", level - 1, key, index, "resourceGroupId"],
            });
        }
        if (!positiveInteger(reward.weight)) {
            context.addIssue({
                code: "custom",
                message: `第 ${level} 级奖励权重必须大于 0`,
                path: ["levels", level - 1, key, index, "weight"],
            });
        }
        if (!positiveInteger(reward.quantity)) {
            context.addIssue({
                code: "custom",
                message: `第 ${level} 级奖励数量必须大于 0`,
                path: ["levels", level - 1, key, index, "quantity"],
            });
        }
    });
}

function validNonNegativeInteger(value: unknown) {
    const number = Number(value);
    return Number.isInteger(number) && number >= 0;
}

function positiveInteger(value: unknown) {
    const number = Number(value);
    return Number.isInteger(number) && number > 0;
}
