import { z } from "zod";
import { cpRelationTypeOptions, resourceIdentityAutoGrantTypes } from "@/features/resources/constants.js";
import { hasUnconfirmedMp4Layout } from "@/features/resources/mp4AlphaLayout.js";
import {
    resourceRequiresExplicitVisualFormat,
    roomBorderFormatOptions,
    roomNameStyleInputError,
} from "@/features/resources/resourceMetadata.js";

const resourceTypes = [
    "avatar_frame",
    "profile_card",
    "coin",
    "vehicle",
    "chat_bubble",
    "badge",
    "floating_screen",
    "gift",
    "mic_seat_icon",
    "mic_seat_animation",
    "room_border",
    "room_name_style",
    "emoji_pack",
    "vip_trial_card",
];
const walletAssetTypes = ["COIN"];
const resourcePriceTypes = ["coin", "free"];
const avatarFrameKinds = ["normal", "level"];
const badgeForms = ["strip", "tile"];
const badgeKinds = ["normal", "level"];
const badgeLevelTracks = ["wealth", "game", "charm"];
const resourceShopDurations = ["1", "3", "7"];
const cpRelationTypes = cpRelationTypeOptions.map(([value]) => value);
const optionalWalletAssetTypeSchema = z
    .preprocess((value) => {
        if (typeof value !== "string") {
            return value;
        }
        const normalized = value.trim().toUpperCase();
        return normalized || undefined;
    }, z.string().optional())
    .refine((value) => !value || walletAssetTypes.includes(value), "请选择金币");

export const resourceCreateFormSchema = z
    .object({
        animationUrl: z.string().trim().max(512, "动效素材不能超过 512 个字符"),
        avatarFrameKind: z.enum(avatarFrameKinds).optional(),
        badgeForm: z.enum(badgeForms).optional(),
        badgeKind: z.enum(badgeKinds).optional(),
        enabled: z.boolean(),
        levelTrack: z.enum(badgeLevelTracks).optional().or(z.literal("")),
        managerGrantEnabled: z.boolean(),
        metadataJson: z.string().trim().max(4096, "资源元数据不能超过 4096 个字符").optional(),
        name: z.string().trim().min(1, "请输入资源名称").max(128, "资源名称不能超过 128 个字符"),
        coinPrice: z.union([z.string(), z.number()]).optional(),
        previewUrl: z.string().trim().max(512, "资源封面不能超过 512 个字符"),
        priceType: z.enum(resourcePriceTypes, "请选择价格类型"),
        resourceCode: z.string().trim().min(1, "请输入资源编码").max(96, "资源编码不能超过 96 个字符"),
        resourceType: z.enum(resourceTypes, "请选择资源类型"),
        roomBorderFormat: z.string().optional(),
        roomNameAngleDegrees: z.union([z.string(), z.number()]).optional(),
        roomNameStops: z.string().optional(),
        roomNameTextColors: z.string().optional(),
        walletAssetAmount: z.union([z.string(), z.number()]).optional(),
    })
    .superRefine((value, context) => {
        // 彩色房名是纯样式资源，不要求伪造图片 URL；其他既有资源继续保持封面和素材的原校验边界。
        if (value.resourceType !== "room_name_style") {
            if (!value.previewUrl) {
                context.addIssue({ code: "custom", message: "请上传资源封面", path: ["previewUrl"] });
            }
            if (!value.animationUrl) {
                context.addIssue({ code: "custom", message: "请上传动效素材", path: ["animationUrl"] });
            }
        } else {
            const styleError = roomNameStyleInputError(value);
            if (styleError) {
                context.addIssue({ code: "custom", message: styleError, path: ["roomNameTextColors"] });
            }
        }
        if (
            resourceRequiresExplicitVisualFormat(value.resourceType) &&
            !roomBorderFormatOptions.includes(value.roomBorderFormat)
        ) {
            context.addIssue({ code: "custom", message: "请选择视觉资源素材格式", path: ["roomBorderFormat"] });
        }
        if (value.resourceType !== "coin") {
            if (value.resourceType === "badge" && !value.badgeForm) {
                context.addIssue({
                    code: "custom",
                    message: "请选择徽章属性",
                    path: ["badgeForm"],
                });
            }
            if (value.resourceType === "badge" && value.badgeKind === "level" && !value.levelTrack) {
                context.addIssue({
                    code: "custom",
                    message: "请选择等级徽章所属等级",
                    path: ["levelTrack"],
                });
            }
            if (value.resourceType === "avatar_frame" && value.avatarFrameKind === "level" && !value.levelTrack) {
                context.addIssue({
                    code: "custom",
                    message: "请选择等级头像框所属等级",
                    path: ["levelTrack"],
                });
            }
        } else {
            const amount = Number(value.walletAssetAmount);
            if (!Number.isInteger(amount) || amount <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入金币数量",
                    path: ["walletAssetAmount"],
                });
            }
        }
        if (value.priceType === "coin") {
            const coinPrice = Number(value.coinPrice);
            if (!Number.isInteger(coinPrice) || coinPrice <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入资源价格",
                    path: ["coinPrice"],
                });
            }
        }
        if (hasUnconfirmedMp4Layout(value.metadataJson)) {
            context.addIssue({
                code: "custom",
                message: "请确认 MP4 透明布局",
                path: ["metadataJson"],
            });
        }
    });

export const resourceFormSchema = resourceCreateFormSchema;

export const emojiPackFormSchema = z.object({
    animationUrl: z.string().trim().min(1, "请上传动效图").max(512, "动效图不能超过 512 个字符"),
    category: z.string().trim().min(1, "请输入分类").max(64, "分类不能超过 64 个字符"),
    coverUrl: z.string().trim().min(1, "请上传封面图").max(512, "封面图不能超过 512 个字符"),
    name: z.string().trim().min(1, "请输入名称").max(128, "名称不能超过 128 个字符"),
    pricingType: z.enum(["free", "paid"]),
    regionIds: z.array(z.union([z.string(), z.number()])).optional(),
    sortOrder: z.union([z.string(), z.number()]).optional(),
});

const groupItemSchema = z.object({
    durationDays: z.union([z.string(), z.number()]).optional(),
    itemType: z.enum(["resource", "wallet_asset"]),
    resourceId: z.union([z.string(), z.number()]).optional(),
    sortOrder: z.union([z.string(), z.number()]).optional(),
    walletAssetAmount: z.union([z.string(), z.number()]).optional(),
    walletAssetType: optionalWalletAssetTypeSchema,
});

export const resourceGroupCreateFormSchema = z
    .object({
        description: z.string().trim().max(512, "资源组说明不能超过 512 个字符").optional(),
        enabled: z.boolean(),
        groupCode: z.string().trim().min(1, "请输入资源组编码").max(96, "资源组编码不能超过 96 个字符"),
        items: z.array(groupItemSchema).min(1, "请至少配置一个资源组条目"),
        name: z.string().trim().min(1, "请输入资源组名称").max(128, "资源组名称不能超过 128 个字符"),
        sortOrder: z.union([z.string(), z.number()]).optional(),
    })
    .superRefine((value, context) => {
        const resourceIds = new Set();
        const walletAssets = new Set();
        value.items.forEach((item, index) => {
            if (item.itemType === "wallet_asset") {
                const amount = Number(item.walletAssetAmount);
                if (!item.walletAssetType || !Number.isInteger(amount) || amount <= 0) {
                    context.addIssue({
                        code: "custom",
                        message: "请输入金币数量",
                        path: ["items", index, "walletAssetAmount"],
                    });
                }
                if (item.walletAssetType) {
                    if (walletAssets.has(item.walletAssetType)) {
                        context.addIssue({
                            code: "custom",
                            message: "同一种钱包资产不能重复配置",
                            path: ["items", index, "walletAssetType"],
                        });
                    }
                    walletAssets.add(item.walletAssetType);
                }
                return;
            }

            const resourceId = Number(item.resourceId);
            const durationDays = Number(item.durationDays);
            if (!Number.isInteger(resourceId) || resourceId <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请选择资源",
                    path: ["items", index, "resourceId"],
                });
            }
            if (!Number.isInteger(durationDays) || durationDays <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入有效天数",
                    path: ["items", index, "durationDays"],
                });
            }
            if (resourceIds.has(resourceId)) {
                context.addIssue({
                    code: "custom",
                    message: "同一个资源不能重复配置",
                    path: ["items", index, "resourceId"],
                });
            }
            resourceIds.add(resourceId);
        });
    });

const identityAutoGrantItemSchema = z.object({
    identityType: z.enum(resourceIdentityAutoGrantTypes, "请选择身份"),
    resourceGroupId: z.union([z.string(), z.number()]).optional(),
});

export const resourceIdentityAutoGrantFormSchema = z
    .object({
        items: z.array(identityAutoGrantItemSchema),
    })
    .superRefine((value, context) => {
        const requiredIdentityTypes = new Set(resourceIdentityAutoGrantTypes);
        const seenIdentityTypes = new Set();

        if (value.items.length !== resourceIdentityAutoGrantTypes.length) {
            context.addIssue({
                code: "custom",
                message: "必须配置所有身份",
                path: ["items"],
            });
        }

        value.items.forEach((item, index) => {
            if (seenIdentityTypes.has(item.identityType)) {
                context.addIssue({
                    code: "custom",
                    message: "身份不能重复配置",
                    path: ["items", index, "identityType"],
                });
            }
            seenIdentityTypes.add(item.identityType);
            requiredIdentityTypes.delete(item.identityType);

            const resourceGroupId =
                item.resourceGroupId === undefined || item.resourceGroupId === "" ? 0 : Number(item.resourceGroupId);
            if (!Number.isInteger(resourceGroupId) || resourceGroupId < 0) {
                context.addIssue({
                    code: "custom",
                    message: "资源组必须是有效资源组",
                    path: ["items", index, "resourceGroupId"],
                });
            }
        });

        requiredIdentityTypes.forEach((identityType) => {
            context.addIssue({
                code: "custom",
                message: "必须配置所有身份",
                path: ["items", identityType],
            });
        });
    });

export const giftFormSchema = z
    .object({
        chargeAssetType: z.enum(["COIN"]),
        coinPrice: z.union([z.string(), z.number()]),
        cpRelationType: z.string().trim().optional(),
        effectTypes: z.array(z.enum(["animation", "music", "global_broadcast"])).optional(),
        effectiveFrom: z.string().optional(),
        effectiveTo: z.string().optional(),
        enabled: z.boolean(),
        giftId: z.string().trim().min(1, "请输入礼物 ID").max(96, "礼物 ID 不能超过 96 个字符"),
        giftTypeCode: z
            .string()
            .trim()
            .min(1, "请选择礼物类型")
            .max(32, "礼物类型不能超过 32 个字符")
            .regex(/^[a-z][a-z0-9_]*$/, "礼物类型只能使用小写字母、数字和下划线"),
        name: z.string().trim().min(1, "请输入礼物名称").max(128, "礼物名称不能超过 128 个字符"),
        presentationJson: z.string().trim().optional(),
        priceVersion: z.string().trim().min(1, "请输入价格版本").max(64, "价格版本不能超过 64 个字符"),
        regionIds: z.array(z.union([z.string(), z.number()])).min(1, "请选择区域"),
        resourceId: z.union([z.string(), z.number()]),
        sortOrder: z.union([z.string(), z.number()]).optional(),
    })
    .superRefine((value, context) => {
        const resourceId = Number(value.resourceId);
        const coinPrice = Number(value.coinPrice);
        const effectiveFromMs = datetimeLocalToMs(value.effectiveFrom);
        const effectiveToMs = datetimeLocalToMs(value.effectiveTo);

        if (!Number.isInteger(resourceId) || resourceId <= 0) {
            context.addIssue({
                code: "custom",
                message: "请选择礼物资源",
                path: ["resourceId"],
            });
        }
        if (!Number.isInteger(coinPrice) || coinPrice < 0) {
            context.addIssue({
                code: "custom",
                message: "请输入价格",
                path: ["coinPrice"],
            });
        }
        if (value.giftTypeCode === "cp" && !cpRelationTypes.includes(value.cpRelationType)) {
            context.addIssue({
                code: "custom",
                message: "请选择关系类型",
                path: ["cpRelationType"],
            });
        }
        if (effectiveFromMs < 0) {
            context.addIssue({
                code: "custom",
                message: "请选择有效开始时间",
                path: ["effectiveFrom"],
            });
        }
        if (effectiveToMs < 0) {
            context.addIssue({
                code: "custom",
                message: "请选择有效结束时间",
                path: ["effectiveTo"],
            });
        }
        if (effectiveFromMs > 0 && effectiveToMs > 0 && effectiveToMs <= effectiveFromMs) {
            context.addIssue({
                code: "custom",
                message: "有效结束时间必须晚于开始时间",
                path: ["effectiveTo"],
            });
        }
        value.regionIds.forEach((regionId, index) => {
            const normalizedRegionId = Number(regionId);
            if (!Number.isInteger(normalizedRegionId) || normalizedRegionId < 0) {
                context.addIssue({
                    code: "custom",
                    message: "请选择区域",
                    path: ["regionIds", index],
                });
            }
        });
        if (value.presentationJson) {
            try {
                JSON.parse(value.presentationJson);
            } catch {
                context.addIssue({
                    code: "custom",
                    message: "展示配置必须是合法 JSON",
                    path: ["presentationJson"],
                });
            }
        }
    });

const giftTypeTabKeySchema = z
    .string()
    .trim()
    .min(1, "Tab Key 不能为空")
    .max(32, "Tab Key 不能超过 32 个字符")
    .regex(/^[a-z][a-z0-9_]*$/, "Tab Key 只能使用小写字母、数字和下划线");

export const giftTypeConfigFormSchema = z.object({
    items: z
        .array(
            z.object({
                enabled: z.boolean(),
                displayName: z.string().trim().min(1, "请输入显示名称").max(64, "显示名称不能超过 64 个字符"),
                sortOrder: z.union([z.string(), z.number()]).optional(),
                tabKey: giftTypeTabKeySchema,
                tabName: z.string().trim().min(1, "请输入 Tab Name").max(32, "Tab Name 不能超过 32 个字符"),
            }),
        )
        .min(1, "请至少保留一个礼物类型"),
});

export const resourceShopItemsFormSchema = z
    .object({
        items: z
            .array(
                z.object({
                    coinPrice: z.union([z.string(), z.number()]),
                    durationDays: z.union([z.string(), z.number()]),
                    effectiveFromMs: z.union([z.string(), z.number()]).optional(),
                    effectiveToMs: z.union([z.string(), z.number()]).optional(),
                    resourceId: z.union([z.string(), z.number()]),
                    shopItemId: z.union([z.string(), z.number()]).optional(),
                    sortOrder: z.union([z.string(), z.number()]).optional(),
                    status: z.enum(["active", "disabled"]).optional(),
                }),
            )
            .min(1, "请至少选择一个资源"),
    })
    .superRefine((value, context) => {
        const specificationKeys = new Set();
        value.items.forEach((item, index) => {
            const resourceId = Number(item.resourceId);
            const durationDays = String(item.durationDays || "").trim();
            const coinPrice = Number(item.coinPrice);
            const effectiveFromMs = optionalEpochMs(item.effectiveFromMs);
            const effectiveToMs = optionalEpochMs(item.effectiveToMs);
            const sortOrder = Number(item.sortOrder || 0);
            const specificationKey = `${resourceId}:${durationDays}`;

            if (!Number.isInteger(resourceId) || resourceId <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请选择资源",
                    path: ["items", index, "resourceId"],
                });
            }
            if (specificationKeys.has(specificationKey)) {
                context.addIssue({
                    code: "custom",
                    message: "同一个资源的相同售卖天数不能重复添加",
                    path: ["items", index, "durationDays"],
                });
            }
            specificationKeys.add(specificationKey);
            if (!resourceShopDurations.includes(durationDays)) {
                context.addIssue({
                    code: "custom",
                    message: "售卖天数只能选择 1、3、7 天",
                    path: ["items", index, "durationDays"],
                });
            }
            if (!Number.isSafeInteger(coinPrice) || coinPrice <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入大于 0 的售卖价格",
                    path: ["items", index, "coinPrice"],
                });
            }
            if (effectiveFromMs < 0) {
                context.addIssue({
                    code: "custom",
                    message: "请选择生效开始时间",
                    path: ["items", index, "effectiveFromMs"],
                });
            }
            if (effectiveToMs < 0) {
                context.addIssue({
                    code: "custom",
                    message: "请选择生效结束时间",
                    path: ["items", index, "effectiveToMs"],
                });
            }
            if (effectiveFromMs > 0 && effectiveToMs > 0 && effectiveToMs <= effectiveFromMs) {
                context.addIssue({
                    code: "custom",
                    message: "生效结束时间必须晚于开始时间",
                    path: ["items", index, "effectiveToMs"],
                });
            }
            if (!Number.isInteger(sortOrder) || sortOrder < 0) {
                context.addIssue({
                    code: "custom",
                    message: "排序不能小于 0",
                    path: ["items", index, "sortOrder"],
                });
            }
        });
    });

function optionalEpochMs(value) {
    const normalized = String(value ?? "").trim();
    if (!normalized) {
        return 0;
    }
    const parsed = Number(normalized);
    return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : -1;
}

function datetimeLocalToMs(value) {
    const trimmed = String(value || "").trim();
    if (!trimmed) {
        return 0;
    }
    const parsed = new Date(trimmed).getTime();
    return Number.isFinite(parsed) ? parsed : -1;
}

export const resourceGrantFormSchema = z
    .object({
        durationDays: z.union([z.string(), z.number()]).optional(),
        groupId: z.union([z.string(), z.number()]).optional(),
        quantity: z.union([z.string(), z.number()]).optional(),
        reason: z.string().trim().min(1, "请输入原因").max(240, "原因不能超过 240 个字符"),
        resourceId: z.union([z.string(), z.number()]).optional(),
        resourceIds: z.array(z.union([z.string(), z.number()])).optional(),
        subjectType: z.enum(["resource", "resource_group", "vip", "vip_trial_card"]),
        targetUserId: z.union([z.string(), z.number()]),
        vipLevel: z.union([z.string(), z.number()]).optional(),
    })
    .superRefine((value, context) => {
        const targetUserId = String(value.targetUserId || "").trim();
        const resourceIds = grantResourceIds(value);
        const groupId = Number(value.groupId || 0);
        const quantity = Number(value.quantity || 1);
        const durationDays = Number(value.durationDays || 0);
        const vipLevel = Number(value.vipLevel || 0);

        if (!/^[1-9]\d*$/.test(targetUserId)) {
            context.addIssue({
                code: "custom",
                message: "请输入用户 ID",
                path: ["targetUserId"],
            });
        }
        if (value.subjectType === "resource") {
            if (!resourceIds.length) {
                context.addIssue({
                    code: "custom",
                    message: "请选择资源",
                    path: ["resourceIds"],
                });
            }
            resourceIds.forEach((resourceIdValue, index) => {
                const resourceId = Number(resourceIdValue || 0);
                if (!Number.isInteger(resourceId) || resourceId <= 0) {
                    context.addIssue({
                        code: "custom",
                        message: "请选择资源",
                        path: ["resourceIds", index],
                    });
                }
            });
            if (!Number.isInteger(quantity) || quantity <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入数量",
                    path: ["quantity"],
                });
            }
            if (!Number.isFinite(durationDays) || durationDays < 0) {
                context.addIssue({
                    code: "custom",
                    message: "请输入有效天数",
                    path: ["durationDays"],
                });
            }
        }
        if (value.subjectType === "resource_group" && (!Number.isInteger(groupId) || groupId <= 0)) {
            context.addIssue({
                code: "custom",
                message: "请选择资源组",
                path: ["groupId"],
            });
        }
        if (
            (value.subjectType === "vip" || value.subjectType === "vip_trial_card") &&
            (!Number.isInteger(vipLevel) || vipLevel <= 0)
        ) {
            context.addIssue({
                code: "custom",
                message: "请选择VIP等级",
                path: ["vipLevel"],
            });
        }
        if (value.subjectType === "vip_trial_card") {
            if (!Number.isInteger(durationDays) || durationDays <= 0) {
                context.addIssue({
                    code: "custom",
                    message: "VIP体验卡有效天数必须大于 0",
                    path: ["durationDays"],
                });
            }
        }
    });

function grantResourceIds(value) {
    if (Array.isArray(value.resourceIds) && value.resourceIds.length) {
        return value.resourceIds;
    }
    return value.resourceId ? [value.resourceId] : [];
}
