import { z } from "zod";

const statusValues = ["active", "disabled"] as const;
const settlementModes = ["daily", "half_month"] as const;
const settlementTriggerModes = ["automatic", "manual"] as const;
const teamPolicyTypes = ["bd", "admin"] as const;

const levelSchema = z.object({
    // 输入框值可能是 string，复制/恢复表单时也可能是 number；统一在 superRefine 中转数值校验。
    agencySalaryUsd: z.union([z.string(), z.number()]),
    hostCoinReward: z.union([z.string(), z.number()]),
    hostSalaryUsd: z.union([z.string(), z.number()]),
    level: z.union([z.string(), z.number()]),
    requiredDiamonds: z.union([z.string(), z.number()]),
    sortOrder: z.union([z.string(), z.number()]).optional(),
    status: z.enum(statusValues),
});

export const hostAgencyPolicyFormSchema = z
    .object({
        effectiveFrom: z.union([z.string(), z.number()]).optional(),
        effectiveTo: z.union([z.string(), z.number()]).optional(),
        enabled: z.boolean(),
        levels: z.array(levelSchema).min(1, "请至少配置一个等级"),
        name: z.string().trim().min(1, "请输入政策名称").max(120, "政策名称不能超过 120 个字符"),
        regionId: z.union([z.string(), z.number()]),
        residualDiamondsPerUsd: z.union([z.string(), z.number()]),
        settlementMode: z.enum(settlementModes),
        settlementTriggerMode: z.enum(settlementTriggerModes),
    })
    .superRefine((value, context) => {
        // 前端先做完整业务校验，降低运营误填成本；后端仍是最终可信校验边界。
        const regionId = Number(value.regionId);
        if (!Number.isInteger(regionId) || regionId <= 0) {
            context.addIssue({ code: "custom", message: "请选择适用区域", path: ["regionId"] });
        }
        if (!isNonNegativeInteger(value.residualDiamondsPerUsd)) {
            context.addIssue({
                code: "custom",
                message: "剩余钻石兑美元配置不正确",
                path: ["residualDiamondsPerUsd"],
            });
        }
        const effectiveFromMs = timeValueToMs(value.effectiveFrom);
        const effectiveToMs = timeValueToMs(value.effectiveTo);
        if (effectiveFromMs < 0 || effectiveToMs < 0 || (effectiveToMs > 0 && effectiveToMs <= effectiveFromMs)) {
            context.addIssue({ code: "custom", message: "生效时间范围不正确", path: ["effectiveTo"] });
        }

        const normalizedLevels = [...value.levels].sort((left, right) => Number(left.level) - Number(right.level));
        const seenLevels = new Set<number>();
        let previousRequiredDiamonds = 0;
        let previousHostSalary = 0;
        let previousHostCoinReward = 0;
        let previousAgencySalary = 0;
        normalizedLevels.forEach((level, index) => {
            // 等级号、钻石门槛和三类累计权益必须单调，保证后续差额结算不会出现负值或多重命中。
            const levelNo = Number(level.level);
            if (!Number.isInteger(levelNo) || levelNo <= 0 || seenLevels.has(levelNo)) {
                context.addIssue({
                    code: "custom",
                    message: "等级必须为不重复的正整数",
                    path: ["levels", index, "level"],
                });
            }
            seenLevels.add(levelNo);
            const requiredDiamonds = Number(level.requiredDiamonds);
            if (
                !Number.isInteger(requiredDiamonds) ||
                requiredDiamonds <= 0 ||
                requiredDiamonds <= previousRequiredDiamonds
            ) {
                context.addIssue({
                    code: "custom",
                    message: "钻石门槛必须逐级递增",
                    path: ["levels", index, "requiredDiamonds"],
                });
            }
            const hostSalary = decimalToScaled(level.hostSalaryUsd, 2);
            if (hostSalary < 0 || hostSalary < previousHostSalary) {
                context.addIssue({
                    code: "custom",
                    message: "主播工资不能小于上一等级",
                    path: ["levels", index, "hostSalaryUsd"],
                });
            }
            const hostCoinReward = Number(level.hostCoinReward);
            if (!Number.isInteger(hostCoinReward) || hostCoinReward < 0 || hostCoinReward < previousHostCoinReward) {
                context.addIssue({
                    code: "custom",
                    message: "金币奖励不能小于上一等级",
                    path: ["levels", index, "hostCoinReward"],
                });
            }
            const agencySalary = decimalToScaled(level.agencySalaryUsd, 2);
            if (agencySalary < 0 || agencySalary < previousAgencySalary) {
                context.addIssue({
                    code: "custom",
                    message: "代理工资不能小于上一等级",
                    path: ["levels", index, "agencySalaryUsd"],
                });
            }
            previousRequiredDiamonds = requiredDiamonds;
            previousHostSalary = hostSalary;
            previousHostCoinReward = hostCoinReward;
            previousAgencySalary = agencySalary;
        });
    });

const teamLevelSchema = z.object({
    level: z.union([z.string(), z.number()]),
    ratePercent: z.union([z.string(), z.number()]),
    salaryUsd: z.union([z.string(), z.number()]),
    sortOrder: z.union([z.string(), z.number()]).optional(),
    status: z.enum(statusValues),
    thresholdUsd: z.union([z.string(), z.number()]),
});

export const teamSalaryPolicyFormSchema = z
    .object({
        effectiveFrom: z.union([z.string(), z.number()]).optional(),
        effectiveTo: z.union([z.string(), z.number()]).optional(),
        enabled: z.boolean(),
        levels: z.array(teamLevelSchema).min(1, "请至少配置一个等级"),
        name: z.string().trim().min(1, "请输入政策名称").max(120, "政策名称不能超过 120 个字符"),
        policyType: z.enum(teamPolicyTypes),
        regionId: z.union([z.string(), z.number()]),
        settlementTriggerMode: z.enum(settlementTriggerModes),
    })
    .superRefine((value, context) => {
        const regionId = Number(value.regionId);
        if (!Number.isInteger(regionId) || regionId <= 0) {
            context.addIssue({ code: "custom", message: "请选择适用区域", path: ["regionId"] });
        }
        const effectiveFromMs = timeValueToMs(value.effectiveFrom);
        const effectiveToMs = timeValueToMs(value.effectiveTo);
        if (effectiveFromMs < 0 || effectiveToMs < 0 || (effectiveToMs > 0 && effectiveToMs <= effectiveFromMs)) {
            context.addIssue({ code: "custom", message: "生效时间范围不正确", path: ["effectiveTo"] });
        }

        const normalizedLevels = [...value.levels].sort((left, right) => Number(left.level) - Number(right.level));
        const seenLevels = new Set<number>();
        let previousThreshold = 0;
        let previousSalary = 0;
        normalizedLevels.forEach((level, index) => {
            // BD/Admin 等级表保存累计门槛和累计工资，递增校验保证后续差额结算不会倒扣。
            const levelNo = Number(level.level);
            if (!Number.isInteger(levelNo) || levelNo <= 0 || seenLevels.has(levelNo)) {
                context.addIssue({
                    code: "custom",
                    message: "等级必须为不重复的正整数",
                    path: ["levels", index, "level"],
                });
            }
            seenLevels.add(levelNo);
            const threshold = decimalToScaled(level.thresholdUsd, 2, false);
            if (threshold <= 0 || threshold <= previousThreshold) {
                context.addIssue({
                    code: "custom",
                    message: "收入门槛必须逐级递增",
                    path: ["levels", index, "thresholdUsd"],
                });
            }
            const rate = decimalToScaled(level.ratePercent, 4, false);
            if (rate <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "提成比例必须大于 0",
                    path: ["levels", index, "ratePercent"],
                });
            }
            const salary = decimalToScaled(level.salaryUsd, 2);
            if (salary < 0 || salary < previousSalary) {
                context.addIssue({
                    code: "custom",
                    message: "累计工资不能小于上一等级",
                    path: ["levels", index, "salaryUsd"],
                });
            }
            previousThreshold = threshold;
            previousSalary = salary;
        });
    });

function isFixedDecimal(value: unknown, scale: number, allowZero: boolean) {
    return decimalToScaled(value, scale, allowZero) >= 0;
}

function isNonNegativeInteger(value: unknown) {
    const raw = String(value ?? "").trim();
    return /^\d+$/.test(raw);
}

function decimalToScaled(value: unknown, scale: number, allowZero = true) {
    // 小数校验转换成整数刻度比较，避免 JS 浮点数直接参与金额大小判断。
    const raw = String(value ?? "").trim();
    if (!raw || raw.startsWith("-")) {
        return -1;
    }
    const pattern = new RegExp(`^\\d+(\\.\\d{1,${scale}})?$`);
    if (!pattern.test(raw)) {
        return -1;
    }
    const [whole, fraction = ""] = raw.split(".");
    const scaled = Number(whole) * 10 ** scale + Number(fraction.padEnd(scale, "0"));
    if (!Number.isSafeInteger(scaled) || (!allowZero && scaled <= 0)) {
        return -1;
    }
    return scaled;
}

function timeValueToMs(value: unknown) {
    // 空值表示长期/立即生效；非法日期返回 -1，让上层统一提示时间范围错误。
    if (value === "" || value === null || value === undefined) {
        return 0;
    }
    if (typeof value === "number") {
        return Number.isFinite(value) && value >= 0 ? value : -1;
    }
    const text = String(value).trim();
    if (!text) {
        return 0;
    }
    const number = Number(value);
    if (/^\d+$/.test(text)) {
        return Number.isFinite(number) ? number : -1;
    }
    const date = new Date(text);
    const ms = date.getTime();
    return Number.isFinite(ms) ? ms : -1;
}
