import { DEFAULT_POOL_ID } from "./api.js";

// AB 实验的分组语义固定为两组：control 是创建实验时的最新启用版本，treatment 是实验发布的新版本。
export const EXPERIMENT_ARMS = ["control", "treatment"];
export const EXPERIMENT_ARM_LABELS = { control: "对照组", treatment: "实验组" };

// 默认 5% 小流量起步：放量在后端是单调的（只增不减不会把已进组用户踢回），
// 起始值必须保守，创建后可以随时在实验管理里调大。
export const DEFAULT_TREATMENT_TRAFFIC_PERCENT = "5";

export function experimentDraft() {
    return {
        name: "",
        trafficPercent: DEFAULT_TREATMENT_TRAFFIC_PERCENT,
        whitelist: [],
    };
}

// 白名单在提交前统一 trim + 去重：Autocomplete freeSolo 允许粘贴带空白的 ID，
// 重复的 user_key 会让 PUT overrides 的 upsert 语义变得不可预测。
export function normalizeWhitelist(values) {
    const seen = new Set();
    const list = [];
    (Array.isArray(values) ? values : []).forEach((value) => {
        const userKey = String(value ?? "").trim();
        if (!userKey || seen.has(userKey)) {
            return;
        }
        seen.add(userKey);
        list.push(userKey);
    });
    return list;
}

// 0 是合法值：表示只有白名单用户进入实验组（灰度验证），不能按“必填大于 0”校验。
export function trafficPercentError(value) {
    const raw = String(value ?? "").trim();
    const parsed = Number(raw);
    if (!raw || !Number.isFinite(parsed) || parsed < 0 || parsed > 100) {
        return "实验组流量必须是 0-100 的百分比（0 表示仅白名单用户进入实验组）";
    }
    return "";
}

export function validateExperimentDraft(draft = {}) {
    const errors = [];
    if (!String(draft.name || "").trim()) {
        errors.push("请填写实验名称");
    }
    const trafficError = trafficPercentError(draft.trafficPercent);
    if (trafficError) {
        errors.push(trafficError);
    }
    return errors;
}

// 组装 POST /experiments 的请求体。config 必须是 formToConfig 的完整输出：
// owner 会把它原子发布为实验组版本，enabled 强制 true——停用的实验组无法开奖，实验没有意义。
export function buildExperimentCreateRequest(draft = {}, config = {}) {
    return {
        config: { ...config, enabled: true },
        name: String(draft.name || "").trim(),
        overrides: normalizeWhitelist(draft.whitelist).map((userKey) => ({ arm: "treatment", user_key: userKey })),
        treatment_traffic_percent: Number(draft.trafficPercent),
    };
}

// 展示层统一去掉尾零：5 -> "5%"、12.5 -> "12.5%"，保留最多两位小数与后端浮点精度一致。
export function formatTrafficPercent(value) {
    const parsed = Number(value);
    if (!Number.isFinite(parsed)) {
        return "0%";
    }
    return `${Number(parsed.toFixed(2))}%`;
}

// paused 也算活跃：暂停只把流量临时切回对照组，实验仍占用该奖池，常规发布仍会被 owner 以 409 拒绝。
export function isActiveExperiment(experiment) {
    return experiment?.status === "running" || experiment?.status === "paused";
}

// 实验按 app+pool 维度独占，不携带 strategy_version：同一奖池的 fixed_v2/dynamic_v3 配置行
// 共享同一个活跃实验的发布封锁，因此关联键必须与 luckyGiftPoolKey 不同（后者含策略版本）。
export function experimentPoolFamilyKey(item = {}) {
    const appCode = String(item.app_code || item.appCode || "")
        .trim()
        .toLowerCase();
    const poolID = String(item.pool_id || item.poolId || DEFAULT_POOL_ID).trim() || DEFAULT_POOL_ID;
    return `${appCode}:${poolID}`;
}

export function activeExperimentsByPool(experiments = []) {
    const byPool = new Map();
    (Array.isArray(experiments) ? experiments : []).forEach((experiment) => {
        if (!isActiveExperiment(experiment)) {
            return;
        }
        const key = experimentPoolFamilyKey(experiment);
        const current = byPool.get(key);
        // 后端保证同一 app+pool 最多一个活跃实验；若数据异常返回多个，保留最近开始的那个，
        // 保证入口指向的实验与 owner 分流实际使用的一致。
        if (!current || Number(experiment.started_at_ms || 0) > Number(current.started_at_ms || 0)) {
            byPool.set(key, experiment);
        }
    });
    return byPool;
}

// 列表与弹窗共用同一份状态徽章口径：running 需要带放量比例，运营扫一眼就知道实验体量。
export function experimentStatusBadge(experiment) {
    if (!experiment) {
        return null;
    }
    if (experiment.status === "running") {
        return { label: `实验中 ${formatTrafficPercent(experiment.treatment_traffic_percent)}`, tone: "warning" };
    }
    if (experiment.status === "paused") {
        return { label: "实验暂停", tone: "warning" };
    }
    if (experiment.status === "completed") {
        return { label: "实验已结束", tone: "stopped" };
    }
    return null;
}

export function experimentArmStat(experiment, arm) {
    return (Array.isArray(experiment?.arm_stats) ? experiment.arm_stats : []).find((stat) => stat.arm === arm) || null;
}
