import { z } from "zod";
import { validatePublicAppJumpParam } from "@/shared/app-jump/appJumpConfig.js";

const appBannerDisplayScopes = ["home", "room", "recharge", "me"] as const;
const systemMessagePushTargetScopes = ["all_registered_users", "user_ids"] as const;
const systemMessagePushActionTypes = [
    "",
    "activity_detail",
    "app_h5",
    "room_detail",
    "user_profile",
    "wallet_withdraw_detail",
    "host_application_detail",
    "coin_seller_transfer_detail",
] as const;

const requiredH5LinkURLSchema = z
    .string()
    .trim()
    .min(1, "请填写 H5 链接")
    .max(2048, "H5 链接不能超过 2048 个字符")
    .refine((value) => !/\s/.test(value), "H5 链接不能包含空白字符");

const h5LinkKeySchema = z
    .string()
    .trim()
    .min(1, "请填写 key")
    .max(80, "key 不能超过 80 个字符")
    .regex(/^[A-Za-z0-9_.:-]+$/, "key 只能包含字母、数字、下划线、中横线、点和冒号");

export const h5LinkUpdateSchema = z.object({
    key: h5LinkKeySchema,
    label: z.string().trim().min(1, "请填写配置项").max(80, "配置项不能超过 80 个字符"),
    url: requiredH5LinkURLSchema,
});

export type H5LinkUpdateForm = z.infer<typeof h5LinkUpdateSchema>;

export const exploreTabSchema = z.object({
    enabled: z.boolean(),
    h5Url: requiredH5LinkURLSchema,
    sortOrder: z.coerce.number().int("排序必须是整数").default(0),
    tab: z.string().trim().min(1, "请填写 tab").max(40, "tab 不能超过 40 个字符"),
});

export type ExploreTabForm = z.infer<typeof exploreTabSchema>;

export function parseSystemMessagePushUserIds(value: string): string[] {
    const tokens = String(value || "")
        .split(/[\s,，]+/)
        .map((item) => item.trim())
        .filter(Boolean);
    const invalid = tokens.find((item) => !/^[1-9]\d*$/.test(item));
    if (invalid) {
        throw new Error("用户 ID 必须是正整数");
    }
    return Array.from(new Set(tokens));
}

export const systemMessagePushSchema = z
    .object({
        actionParam: z.string().trim().max(2048, "跳转参数不能超过 2048 个字符").default(""),
        actionType: z.enum(systemMessagePushActionTypes).default(""),
        body: z.string().trim().max(4000, "正文不能超过 4000 个字符").default(""),
        summary: z.string().trim().min(1, "请填写摘要").max(240, "摘要不能超过 240 个字符"),
        targetScope: z.enum(systemMessagePushTargetScopes),
        title: z.string().trim().min(1, "请填写标题").max(80, "标题不能超过 80 个字符"),
        userIdsText: z.string().trim().default(""),
    })
    .superRefine((value, ctx) => {
        if (value.targetScope === "user_ids") {
            let userIds: string[];
            try {
                userIds = parseSystemMessagePushUserIds(value.userIdsText);
            } catch (error) {
                ctx.addIssue({
                    code: z.ZodIssueCode.custom,
                    message: error instanceof Error ? error.message : "用户 ID 必须是正整数",
                    path: ["userIdsText"],
                });
                return;
            }
            if (!userIds.length) {
                ctx.addIssue({
                    code: z.ZodIssueCode.custom,
                    message: "用户 ID 列表不能为空",
                    path: ["userIdsText"],
                });
            }
        }

        if (value.actionParam && !value.actionType) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: "请选择跳转类型",
                path: ["actionType"],
            });
        }
    });

export type SystemMessagePushForm = z.infer<typeof systemMessagePushSchema>;

export const appBannerSchema = z
    .object({
        bannerType: z.enum(["h5", "app"]),
        countryCode: z
            .string()
            .trim()
            .transform((value) => value.toUpperCase())
            .refine((value) => value === "" || /^[A-Z]{2,3}$/.test(value), "国家编码需为 2-3 位字母"),
        coverUrl: z
            .string()
            .trim()
            .min(1, "请上传封面图")
            .max(1024, "封面图地址不能超过 1024 个字符")
            .refine((value) => !/\s/.test(value), "封面图地址不能包含空白字符"),
        description: z.string().trim().max(255, "描述不能超过 255 个字符"),
        displayScope: z.enum(appBannerDisplayScopes).optional(),
        displayScopes: z.array(z.enum(appBannerDisplayScopes)).min(1, "请选择显示范围"),
        endsAtMs: z.coerce.number().int().min(0, "投放结束时间不正确").default(0),
        param: z.string().trim().max(2048, "参数不能超过 2048 个字符"),
        platform: z.enum(["android", "ios"]),
        regionId: z.coerce.number().int().min(0, "区域不正确").default(0),
        roomSmallImageUrl: z
            .string()
            .trim()
            .max(1024, "房间内小屏图地址不能超过 1024 个字符")
            .refine((value) => !/\s/.test(value), "房间内小屏图地址不能包含空白字符"),
        sortOrder: z.coerce.number().int("排序必须是整数").default(0),
        startsAtMs: z.coerce.number().int().min(0, "投放开始时间不正确").default(0),
        status: z.enum(["active", "disabled", "expired"]),
    })
    .superRefine((value, ctx) => {
        if (value.bannerType === "h5" && !value.param) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "H5 类型需要填写链接", path: ["param"] });
        }
        if (value.bannerType === "h5" && /\s/.test(value.param)) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "H5 链接不能包含空白字符", path: ["param"] });
        }
        if (value.bannerType === "app") {
            const validation = validatePublicAppJumpParam(value.param);
            if (!validation.valid) {
                ctx.addIssue({ code: z.ZodIssueCode.custom, message: validation.message, path: ["param"] });
            }
        }
        if (value.displayScopes.includes("room") && !value.roomSmallImageUrl) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: "房间内显示需要上传房间内小屏图",
                path: ["roomSmallImageUrl"],
            });
        }
        if (value.startsAtMs > 0 && value.endsAtMs > 0 && value.startsAtMs >= value.endsAtMs) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "投放结束时间必须晚于开始时间", path: ["endsAtMs"] });
        }
    });

export type AppBannerForm = z.infer<typeof appBannerSchema>;

export const appSplashScreenSchema = z
    .object({
        countryCode: z
            .string()
            .trim()
            .transform((value) => value.toUpperCase())
            .refine((value) => value === "" || /^[A-Z]{2,3}$/.test(value), "国家编码需为 2-3 位字母"),
        coverUrl: z
            .string()
            .trim()
            .min(1, "请上传封面图")
            .max(1024, "封面图地址不能超过 1024 个字符")
            .refine((value) => !/\s/.test(value), "封面图地址不能包含空白字符"),
        description: z.string().trim().max(255, "描述不能超过 255 个字符"),
        displayDurationMs: z.coerce.number().int("展示时长必须是整数毫秒").min(0, "展示时长不能小于 0").default(3000),
        endsAtMs: z.coerce.number().int().min(0, "投放结束时间不正确").default(0),
        param: z.string().trim().max(2048, "参数不能超过 2048 个字符"),
        platform: z.enum(["android", "ios"]),
        regionId: z.coerce.number().int().min(0, "区域不正确").default(0),
        sortOrder: z.coerce.number().int("排序必须是整数").default(0),
        splashType: z.enum(["h5", "app"]),
        startsAtMs: z.coerce.number().int().min(0, "投放开始时间不正确").default(0),
        status: z.enum(["active", "disabled", "expired"]),
    })
    .superRefine((value, ctx) => {
        if (value.splashType === "h5" && !value.param) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "H5 类型需要填写链接", path: ["param"] });
        }
        if (value.splashType === "h5" && /\s/.test(value.param)) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "H5 链接不能包含空白字符", path: ["param"] });
        }
        if (value.splashType === "app") {
            const validation = validatePublicAppJumpParam(value.param);
            if (!validation.valid) {
                ctx.addIssue({ code: z.ZodIssueCode.custom, message: validation.message, path: ["param"] });
            }
        }
        if (value.startsAtMs > 0 && value.endsAtMs > 0 && value.startsAtMs >= value.endsAtMs) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "投放结束时间必须晚于开始时间", path: ["endsAtMs"] });
        }
    });

export type AppSplashScreenForm = z.infer<typeof appSplashScreenSchema>;

export const appPopupSchema = z
    .object({
        code: z
            .string()
            .trim()
            .min(1, "请填写弹窗code")
            .max(80, "弹窗code不能超过 80 个字符")
            .regex(/^[A-Za-z0-9_.:-]+$/, "弹窗code只能包含字母、数字、下划线、中横线、点和冒号"),
        displayPeriodDays: z.coerce.number().int("展示周期必须是整数天").min(0, "展示周期不能小于 0").default(0),
        endsAtMs: z.coerce.number().int().min(0, "生效结束时间不正确").default(0),
        imageUrl: z
            .string()
            .trim()
            .max(1024, "图片地址不能超过 1024 个字符")
            .refine((value) => !/\s/.test(value), "图片地址不能包含空白字符"),
        jumpType: z.enum(["h5", "app"]),
        jumpUrl: z.string().trim().min(1, "请填写跳转地址").max(2048, "跳转地址不能超过 2048 个字符"),
        name: z.string().trim().min(1, "请填写弹窗名字").max(80, "弹窗名字不能超过 80 个字符"),
        sortOrder: z.coerce.number().int("排序必须是整数").default(0),
        startsAtMs: z.coerce.number().int().min(0, "生效开始时间不正确").default(0),
        status: z.enum(["active", "disabled", "expired"]),
    })
    .superRefine((value, ctx) => {
        if (value.jumpType === "h5" && /\s/.test(value.jumpUrl)) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "H5 链接不能包含空白字符", path: ["jumpUrl"] });
        }
        if (value.jumpType === "app") {
            const validation = validatePublicAppJumpParam(value.jumpUrl);
            if (!validation.valid) {
                ctx.addIssue({ code: z.ZodIssueCode.custom, message: validation.message, path: ["jumpUrl"] });
            }
        }
        if (value.startsAtMs > 0 && value.endsAtMs > 0 && value.startsAtMs >= value.endsAtMs) {
            ctx.addIssue({ code: z.ZodIssueCode.custom, message: "生效结束时间必须晚于开始时间", path: ["endsAtMs"] });
        }
    });

export type AppPopupForm = z.infer<typeof appPopupSchema>;

export const appVersionSchema = z.object({
    buildNumber: z.coerce.number().int("编译版本号必须是整数").positive("编译版本号必须大于 0"),
    description: z.string().trim().max(1000, "更新描述不能超过 1000 个字符").default(""),
    downloadUrl: z
        .string()
        .trim()
        .min(1, "请填写下载链接")
        .max(2048, "下载链接不能超过 2048 个字符")
        .refine((value) => !/\s/.test(value), "下载链接不能包含空白字符"),
    forceUpdate: z.boolean(),
    platform: z.enum(["android", "ios"]),
    version: z.string().trim().min(1, "请填写版本号").max(40, "版本号不能超过 40 个字符"),
});

export type AppVersionForm = z.infer<typeof appVersionSchema>;
