const Sequelize = require("sequelize");
const op = Sequelize.Op;
const baseModel = require("../../middleware/baseModel");

function currentStatMonth(d = new Date()) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  return `${y}-${m}`;
}

function num(v) {
  if (v === null || v === undefined || v === "") return 0;
  const n = Number(v);
  return Number.isNaN(n) ? 0 : n;
}

/** 0 表示无限制；已用量超过 limit 则超限（允许用到等于 limit） */
function quotaExceeded(used, limit) {
  const li = num(limit);
  if (li <= 0) return false;
  return num(used) > li;
}

/**
 * 取或创建当月用量行
 */
async function getOrCreateUsage(userId, planId, statMonth) {
  const [row] = await baseModel.biz_usage_monthly.findOrCreate({
    where: { user_id: userId, stat_month: statMonth },
    defaults: {
      user_id: userId,
      plan_id: planId,
      stat_month: statMonth,
      msg_count: 0,
      mass_count: 0,
      friend_count: 0,
      sns_count: 0,
      active_user_count: 0,
      api_call_count: 0,
    },
  });
  if (num(row.plan_id) !== num(planId)) {
    await row.update({ plan_id: planId });
  }
  return row;
}

async function applyDelta(userId, planId, statMonth, delta) {
  const row = await getOrCreateUsage(userId, planId, statMonth);
  const next = {
    msg_count: num(row.msg_count) + num(delta.msg),
    mass_count: num(row.mass_count) + num(delta.mass),
    friend_count: num(row.friend_count) + num(delta.friend),
    sns_count: num(row.sns_count) + num(delta.sns),
    active_user_count: num(row.active_user_count) + num(delta.active_user),
  };
  await row.update(next);
  return row.reload();
}

/**
 * 校验「增量」后是否超限（与套餐额度对比）
 * feature: msg | mass | friend | sns | active_user
 */
function checkQuotaAfterDelta(plan, usageRow, delta) {
  const checks = [
    ["msg", "msg_count", "msg_quota"],
    ["mass", "mass_count", "mass_quota"],
    ["friend", "friend_count", "friend_quota"],
    ["sns", "sns_count", "sns_quota"],
    ["active_user", "active_user_count", "active_user_limit"],
  ];
  for (const [key, uCol, pCol] of checks) {
    const add = num(delta[key]);
    if (add <= 0) continue;
    const used = num(usageRow[uCol]) + add;
    if (quotaExceeded(used, plan[pCol])) {
      return { ok: false, error_code: "QUOTA_EXCEEDED", message: `额度不足: ${key}` };
    }
  }
  return { ok: true };
}

/**
 * 为当前月所有有效订阅补用量行（月结/初始化）
 */
async function ensureUsageRowsForCurrentMonth() {
  const statMonth = currentStatMonth();
  const now = new Date();
  const subs = await baseModel.biz_subscription.findAll({
    where: {
      status: "active",
      start_time: { [op.lte]: now },
      end_time: { [op.gte]: now },
    },
  });
  let n = 0;
  for (const s of subs) {
    await getOrCreateUsage(s.user_id, s.plan_id, statMonth);
    n += 1;
  }
  return n;
}

/**
 * 校验 API 调用次数是否超限
 * @param {object} plan - 套餐记录（含 api_call_quota）
 * @param {object} usageRow - 当月用量记录（含 api_call_count）
 * @returns {{ ok: boolean, error_code?: string, message?: string }}
 */
function checkApiCallQuota(plan, usageRow) {
  const quota = num(plan.api_call_quota);
  if (quota <= 0) return { ok: true };
  const used = num(usageRow.api_call_count) + 1;
  if (used > quota) {
    return { ok: false, error_code: "API_CALL_QUOTA_EXCEEDED", message: `当月 API 调用次数已达上限(${quota})` };
  }
  return { ok: true };
}

/**
 * API 调用次数 +1
 */
async function incrementApiCallCount(userId, planId, statMonth) {
  const row = await getOrCreateUsage(userId, planId, statMonth);
  await row.update({ api_call_count: num(row.api_call_count) + 1 });
  return row.reload();
}

/**
 * 校验接口路径是否在套餐允许范围内
 * @param {object} plan - 套餐记录（含 allowed_apis）
 * @param {string} apiPath - 当前请求的接口路径，如 /user/GetProfile
 * @returns {{ ok: boolean, error_code?: string, message?: string }}
 */
function checkApiPathAllowed(plan, apiPath) {
  const allowed = plan.allowed_apis;
  // null / undefined：不限制接口
  if (allowed == null) return { ok: true };
  let list = allowed;
  if (typeof list === "string") {
    try {
      list = JSON.parse(list);
    } catch {
      return { ok: true };
    }
  }
  if (!Array.isArray(list)) return { ok: true };
  // 空数组：明确配置为「不允许任何转发接口」
  if (list.length === 0) {
    return { ok: false, error_code: "API_NOT_ALLOWED", message: "当前套餐未开放任何接口" };
  }
  if (list.includes(apiPath)) return { ok: true };
  return { ok: false, error_code: "API_NOT_ALLOWED", message: `当前套餐不支持该接口: ${apiPath}` };
}

module.exports = {
  currentStatMonth,
  getOrCreateUsage,
  applyDelta,
  checkQuotaAfterDelta,
  ensureUsageRowsForCurrentMonth,
  checkApiCallQuota,
  incrementApiCallCount,
  checkApiPathAllowed,
  num,
};
