// 社交 BI v2 的指标口径中心：所有视图通过 METRIC_DEFS 取 label/格式化/口径说明，
// 行数据保持后端原始 snake_case 字段（金额 USD 分、比例 0-1），渲染时才格式化。

import { formatCompact, formatCount, formatDurationMs, formatMoneyMinor, formatRatioPercent, isBlank } from "./format.js";

export const METRIC_DEFS = {
  new_users: { label: "新增", tooltip: "当日新注册用户数（legacy 按 user_run_profile 创建时间）", type: "count" },
  active_users: { label: "日活 (DAU)", tooltip: "当日活跃去重用户；跨天合计为人天", type: "count" },
  paid_users: { label: "付费用户", tooltip: "发生成功充值的去重用户", type: "count" },
  recharge_users: { label: "充值用户", tooltip: "与付费用户同口径", type: "count" },
  recharge_usd_minor: {
    label: "充值 ($)",
    tooltip: "Finance 口径成功充值合计（谷歌 + 非谷歌三方 + 币商，USD）",
    type: "money"
  },
  new_user_recharge_usd_minor: { label: "新用户充值", tooltip: "Finance 暂无新用户充值拆分，当前不展示", type: "money" },
  google_recharge_usd_minor: { label: "谷歌充值", tooltip: "Finance 口径 Google 成功充值", type: "money" },
  mifapay_recharge_usd_minor: { label: "三方充值", tooltip: "Finance 口径非 Google 三方成功充值", type: "money" },
  coin_seller_recharge_usd_minor: {
    label: "币商充值",
    tooltip: "Finance 口径已核验币商充值订单 + H5 币商身份成功充值",
    type: "money"
  },
  coin_seller_stock_coin: { label: "币商充值金币", tooltip: "币商进货获得的金币", type: "coin" },
  coin_seller_transfer_coin: { label: "币商出货金币", tooltip: "币商转给用户的金币（legacy 按 SELLER_AGENT 流水）", type: "coin" },
  game_turnover: { label: "游戏流水", tooltip: "游戏下注金币流水", type: "coin" },
  game_profit_rate: { label: "游戏利润率", tooltip: "（流水-返奖）/流水", type: "ratio" },
  lucky_gift_turnover: { label: "幸运礼物流水", tooltip: "幸运礼物赠送金币流水", type: "coin" },
  lucky_gift_payout: { label: "幸运礼物返奖", tooltip: "幸运礼物中奖返还金币", type: "coin" },
  lucky_gift_profit_rate: { label: "幸运礼物利润率", tooltip: "（流水-返奖）/流水", type: "ratio" },
  super_lucky_gift_turnover: { label: "超级幸运礼物流水", tooltip: "超级幸运礼物赠送金币流水（legacy 平台无此玩法）", type: "coin" },
  super_lucky_gift_profit_rate: { label: "超级幸运礼物利润率", tooltip: "（流水-返奖）/流水", type: "ratio" },
  gift_coin_spent: { label: "礼物流水", tooltip: "全部礼物赠送金币流水（含幸运礼物）", type: "coin" },
  coin_total: { label: "金币数量", tooltip: "用户金币余额快照", type: "coin" },
  consumed_coin: { label: "消耗金币", tooltip: "金币消耗流水合计（legacy 仅全 App 口径）", type: "coin" },
  output_coin: { label: "产出金币", tooltip: "金币产出流水合计（legacy 仅全 App 口径）", type: "coin" },
  consume_output_ratio: { label: "消耗产出比", tooltip: "消耗金币 / 产出金币", type: "ratio" },
  platform_grant_coin: { label: "平台发放金币", tooltip: "平台活动发放金币", type: "coin" },
  manual_grant_coin: { label: "人工发放金币", tooltip: "后台人工发放金币", type: "coin" },
  salary_usd_minor: { label: "存量工资 ($)", tooltip: "主播工资余额快照（USD）", type: "money" },
  salary_transfer_coin: { label: "工资兑换金币", tooltip: "工资兑换成金币的数量", type: "coin" },
  avg_mic_online_ms: { label: "平均麦上时间", tooltip: "人均麦上时长", type: "duration" },
  mic_online_ms: { label: "麦上总时长", tooltip: "全部用户麦上时长合计", type: "duration" },
  arpu_usd_minor: { label: "ARPU ($)", tooltip: "Finance 充值没有同口径活跃人数，当前不展示", type: "money" },
  arppu_usd_minor: { label: "ARPPU ($)", tooltip: "Finance 币商/H5 充值没有同口径付费人数，当前不展示", type: "money" },
  paid_conversion_rate: { label: "付费转化率", tooltip: "付费用户 / 日活", type: "ratio" },
  recharge_conversion_rate: { label: "充值转化率", tooltip: "充值用户 / 日活", type: "ratio" },
  d1_retention_rate: { label: "次日留存", tooltip: "当日活跃的前 1 日注册用户 / 前 1 日注册数（观察日回看口径）", type: "ratio" },
  d7_retention_rate: { label: "7日留存", tooltip: "当日活跃的前 7 日注册用户 / 前 7 日注册数（观察日回看口径）", type: "ratio" },
  d30_retention_rate: { label: "30日留存", tooltip: "当日活跃的前 30 日注册用户 / 前 30 日注册数（观察日回看口径）", type: "ratio" }
};

// 数据明细宽表的列组：与运营的心智分组一致，支持整组折叠。
export const METRIC_GROUPS = [
  { key: "users", label: "用户", metrics: ["new_users", "active_users", "paid_users", "recharge_users"] },
  {
    key: "recharge",
    label: "充值",
    metrics: [
      "recharge_usd_minor",
      "new_user_recharge_usd_minor",
      "google_recharge_usd_minor",
      "mifapay_recharge_usd_minor",
      "coin_seller_recharge_usd_minor"
    ]
  },
  { key: "coinSeller", label: "币商", metrics: ["coin_seller_stock_coin", "coin_seller_transfer_coin"] },
  {
    key: "play",
    label: "玩法流水",
    metrics: [
      "game_turnover",
      "game_profit_rate",
      "lucky_gift_turnover",
      "lucky_gift_profit_rate",
      "super_lucky_gift_turnover",
      "super_lucky_gift_profit_rate",
      "gift_coin_spent"
    ]
  },
  {
    key: "coins",
    label: "金币",
    metrics: ["coin_total", "consumed_coin", "output_coin", "consume_output_ratio", "platform_grant_coin", "manual_grant_coin"]
  },
  { key: "salary", label: "工资", metrics: ["salary_usd_minor", "salary_transfer_coin"] },
  { key: "engagement", label: "时长", metrics: ["avg_mic_online_ms", "mic_online_ms"] },
  {
    key: "quality",
    label: "质量",
    metrics: [
      "arpu_usd_minor",
      "arppu_usd_minor",
      "paid_conversion_rate",
      "recharge_conversion_rate",
      "d1_retention_rate",
      "d7_retention_rate",
      "d30_retention_rate"
    ]
  }
];

export function metricLabel(key) {
  return METRIC_DEFS[key]?.label || key;
}

export function metricTooltip(key) {
  return METRIC_DEFS[key]?.tooltip || "";
}

export function formatMetric(key, value) {
  const type = METRIC_DEFS[key]?.type;
  if (type === "money") {
    return formatMoneyMinor(value);
  }
  if (type === "ratio") {
    return formatRatioPercent(value);
  }
  if (type === "coin") {
    return formatCount(value);
  }
  if (type === "duration") {
    return formatDurationMs(value);
  }
  return formatCount(value);
}

export function formatMetricCompact(key, value) {
  const type = METRIC_DEFS[key]?.type;
  if (type === "money") {
    return isBlank(value) ? "--" : `$${formatCompact(Number(value) / 100)}`;
  }
  if (type === "ratio") {
    return formatRatioPercent(value);
  }
  if (type === "duration") {
    return formatDurationMs(value);
  }
  return formatCompact(value);
}

// 图表取数值：金额换算成美元，比例换算成百分数，其余原样；缺失返回 null 让 ECharts 断线。
export function metricChartValue(key, value) {
  if (isBlank(value)) {
    return null;
  }
  const type = METRIC_DEFS[key]?.type;
  if (type === "money") {
    return Number(value) / 100;
  }
  if (type === "ratio") {
    return Number(value) * 100;
  }
  return Number(value);
}

// 可线性相加的字段；与后端 databi/metrics.go 的 additiveMetricKeys 对齐，前端聚合只做同一口径。
const ADDITIVE_METRIC_KEYS = [
  "new_users",
  "active_users",
  "paid_users",
  "recharge_users",
  "recharge_usd_minor",
  "new_user_recharge_usd_minor",
  "google_recharge_usd_minor",
  "mifapay_recharge_usd_minor",
  "coin_seller_recharge_usd_minor",
  "coin_seller_stock_coin",
  "coin_seller_transfer_coin",
  "game_turnover",
  "game_payout",
  "lucky_gift_turnover",
  "lucky_gift_payout",
  "super_lucky_gift_turnover",
  "super_lucky_gift_payout",
  "gift_coin_spent",
  "coin_total",
  "consumed_coin",
  "output_coin",
  "platform_grant_coin",
  "manual_grant_coin",
  "salary_usd_minor",
  "salary_transfer_coin",
  "mic_online_ms",
  "mic_online_users",
  "d1_retention_users",
  "d1_retention_base_users",
  "d7_retention_users",
  "d7_retention_base_users",
  "d30_retention_users",
  "d30_retention_base_users"
];

function readNumeric(row, key) {
  const value = row?.[key];
  if (isBlank(value)) {
    return null;
  }
  const numeric = Number(value);
  return Number.isFinite(numeric) ? numeric : null;
}

// 余额快照类指标只在"空间"维度可加（跨国家/区域/App），跨天求和没有业务含义；
// 跨天聚合时取最后一天的快照（与后端整段口径一致）。
const SNAPSHOT_METRIC_KEYS = new Set(["coin_total", "salary_usd_minor"]);

// aggregateMetricMaps 把若干行（App 合计、区域行、日行）合并成一行：
// 可加字段求和（全缺失保持 null → 显示 "--"），比例/均值按分子分母重算，避免"平均百分比"这类错误口径。
// 行集跨多天时传 { acrossTime: true }，快照字段只累计最后一天的行。
export function aggregateMetricMaps(rows, { acrossTime = false } = {}) {
  const out = {};
  // Finance 币商/H5 金额没有与旧 paid_users 一致的去重人数；标记需跨聚合传播，
  // 避免前端把精确金额再次除以旧人数，重新制造混合口径 ARPU/ARPPU。
  const financeRechargeAligned = rows.some((row) => row?.finance_recharge_aligned === true);
  out.finance_recharge_aligned = financeRechargeAligned;
  let latestDay = "";
  if (acrossTime) {
    rows.forEach((row) => {
      const day = String(row?.stat_day || "");
      if (day > latestDay) {
        latestDay = day;
      }
    });
  }
  ADDITIVE_METRIC_KEYS.forEach((key) => {
    const snapshotOnly = acrossTime && SNAPSHOT_METRIC_KEYS.has(key);
    let sum = null;
    rows.forEach((row) => {
      if (snapshotOnly && String(row?.stat_day || "") !== latestDay) {
        return;
      }
      const value = readNumeric(row, key);
      if (value !== null) {
        sum = (sum ?? 0) + value;
      }
    });
    out[key] = sum;
  });

  const recharge = out.recharge_usd_minor;
  const active = out.active_users;
  const paid = out.paid_users;
  out.arpu_usd_minor = !financeRechargeAligned && recharge !== null && active ? Math.round(recharge / active) : null;
  out.arppu_usd_minor = !financeRechargeAligned && recharge !== null && paid ? Math.round(recharge / paid) : null;
  out.paid_conversion_rate = paid !== null && active ? paid / active : null;
  out.recharge_conversion_rate = out.recharge_users !== null && active ? out.recharge_users / active : null;
  out.game_profit_rate = out.game_turnover ? (out.game_turnover - (out.game_payout ?? 0)) / out.game_turnover : null;
  out.lucky_gift_profit_rate = out.lucky_gift_turnover
    ? (out.lucky_gift_turnover - (out.lucky_gift_payout ?? 0)) / out.lucky_gift_turnover
    : null;
  out.super_lucky_gift_profit_rate = out.super_lucky_gift_turnover
    ? (out.super_lucky_gift_turnover - (out.super_lucky_gift_payout ?? 0)) / out.super_lucky_gift_turnover
    : null;
  out.consume_output_ratio = out.consumed_coin !== null && out.output_coin ? out.consumed_coin / out.output_coin : null;
  out.avg_mic_online_ms = out.mic_online_ms !== null && out.mic_online_users ? Math.round(out.mic_online_ms / out.mic_online_users) : null;
  ["d1", "d7", "d30"].forEach((day) => {
    const users = out[`${day}_retention_users`];
    const base = out[`${day}_retention_base_users`];
    out[`${day}_retention_rate`] = users !== null && base ? users / base : null;
  });
  return out;
}

// averageMetricMaps：跨天"平均值"行。可加字段取日均（总量/覆盖天数），余额快照保持末日快照，
// 比例/均值类分子分母同除天数后不变，直接沿用汇总行的派生值。
export function averageMetricMaps(rows, dayCount) {
  if (!rows.length || !dayCount || dayCount <= 0) {
    return null;
  }
  const out = aggregateMetricMaps(rows, { acrossTime: true });
  ADDITIVE_METRIC_KEYS.forEach((key) => {
    if (SNAPSHOT_METRIC_KEYS.has(key)) {
      return;
    }
    if (out[key] !== null && out[key] !== undefined) {
      out[key] = out[key] / dayCount;
    }
  });
  return out;
}

// App 品牌色：chips、图表系列、行标识统一取色，保证同一 App 全站同色。
// 已知 App 用固定映射（与筛选状态无关）；未知 App 按 code 哈希取色，避免"选中子集后颜色漂移"。
const APP_COLOR_PALETTE = ["#2563eb", "#0e9488", "#d97706", "#7c3aed", "#db2777", "#059669", "#dc2626", "#4f46e5"];
const APP_COLOR_FIXED = { aslan: 2, fami: 3, huwaa: 4, lalu: 0, yumi: 1 };

export function appColor(appCode) {
  const code = String(appCode || "").toLowerCase();
  if (code in APP_COLOR_FIXED) {
    return APP_COLOR_PALETTE[APP_COLOR_FIXED[code]];
  }
  let hash = 0;
  for (let index = 0; index < code.length; index += 1) {
    hash = (hash * 31 + code.charCodeAt(index)) >>> 0;
  }
  return APP_COLOR_PALETTE[hash % APP_COLOR_PALETTE.length];
}
