const baseModel = require("../../middleware/baseModel");
const tokenLogic = require("./biz_token_logic");
const usageSvc = require("./biz_usage_service");

function featureAllowed(plan, feature) {
  if (!feature) return true;
  const feats = plan.enabled_features;
  if (feats == null) return true;
  if (Array.isArray(feats)) return feats.includes(feature);
  if (typeof feats === "object") {
    return feats[feature] === true || feats[feature] === 1 || feats[feature] === "1";
  }
  return false;
}

function normalizeUsageDelta(raw) {
  if (!raw || typeof raw !== "object") return {};
  return {
    msg: usageSvc.num(raw.msg ?? raw.msg_count),
    mass: usageSvc.num(raw.mass ?? raw.mass_count),
    friend: usageSvc.num(raw.friend ?? raw.friend_count),
    sns: usageSvc.num(raw.sns ?? raw.sns_count),
    active_user: usageSvc.num(raw.active_user ?? raw.active_user_count),
  };
}

function hasPositiveDelta(delta) {
  return Object.values(delta).some((v) => usageSvc.num(v) > 0);
}

/**
 * 对外鉴权：Token + 用户 + 有效订阅 + 功能点 + 接口权限 + API调用量 + 可选用量上报
 * body: { token, feature?, api_path?, usage_delta?: { msg?, mass?, ... } }
 */
async function verifyRequest(body) {
  const { token, feature, api_path } = body || {};
  if (!token) {
    return { ok: false, error_code: "TOKEN_INVALID", message: "缺少 token" };
  }

  const hash = tokenLogic.hashPlainToken(token);
  const row = await baseModel.biz_api_token.findOne({ where: { token_hash: hash } });
  if (!row) {
    return { ok: false, error_code: "TOKEN_INVALID", message: "Token 不存在" };
  }
  if (row.status === "revoked") {
    return { ok: false, error_code: "TOKEN_REVOKED", message: "Token 已吊销" };
  }

  const now = new Date();
  if (new Date(row.expire_at) < now) {
    return { ok: false, error_code: "TOKEN_EXPIRED", message: "Token 已过期" };
  }

  const user = await baseModel.biz_user.findByPk(row.user_id);
  if (!user || user.status !== "active") {
    return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "用户不可用" };
  }

  const sub = await tokenLogic.findActiveSubscriptionForUser(row.user_id);
  if (!sub) {
    return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "无有效订阅" };
  }

  const plan = await baseModel.biz_plan.findByPk(sub.plan_id);
  if (!plan || plan.status !== "active") {
    return { ok: false, error_code: "SUBSCRIPTION_INACTIVE", message: "套餐不可用" };
  }

  if (feature && !featureAllowed(plan, feature)) {
    return { ok: false, error_code: "FEATURE_NOT_ALLOWED", message: "功能未在套餐内" };
  }

  // 接口路径级权限校验
  if (api_path) {
    const apiCheck = usageSvc.checkApiPathAllowed(plan, api_path);
    if (!apiCheck.ok) {
      return { ok: false, error_code: apiCheck.error_code, message: apiCheck.message };
    }
  }

  const statMonth = usageSvc.currentStatMonth();
  let usageRow = await usageSvc.getOrCreateUsage(row.user_id, sub.plan_id, statMonth);

  // API 调用次数配额校验
  if (api_path) {
    const callCheck = usageSvc.checkApiCallQuota(plan, usageRow);
    if (!callCheck.ok) {
      return { ok: false, error_code: callCheck.error_code, message: callCheck.message };
    }
    usageRow = await usageSvc.incrementApiCallCount(row.user_id, sub.plan_id, statMonth);
  }

  const delta = normalizeUsageDelta(body.usage_delta || body.usage_report);
  if (hasPositiveDelta(delta)) {
    const q = usageSvc.checkQuotaAfterDelta(plan, usageRow, delta);
    if (!q.ok) {
      return { ok: false, error_code: q.error_code || "QUOTA_EXCEEDED", message: q.message || "额度不足" };
    }
    usageRow = await usageSvc.applyDelta(row.user_id, sub.plan_id, statMonth, delta);
  }

  await row.update({ last_used_at: now });

  return {
    ok: true,
    context: {
      user_id: row.user_id,
      plan_id: sub.plan_id,
      subscription_id: sub.id,
      token_id: row.id,
      stat_month: statMonth,
      usage_snapshot: {
        msg_count: usageSvc.num(usageRow.msg_count),
        mass_count: usageSvc.num(usageRow.mass_count),
        friend_count: usageSvc.num(usageRow.friend_count),
        sns_count: usageSvc.num(usageRow.sns_count),
        active_user_count: usageSvc.num(usageRow.active_user_count),
        api_call_count: usageSvc.num(usageRow.api_call_count),
      },
    },
  };
}

module.exports = { verifyRequest };
