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

const MAX_TOKENS_PER_USER = 5;

function hashPlainToken(plain) {
  return crypto.createHash("sha256").update(plain, "utf8").digest("hex");
}

function generatePlainToken() {
  return `waw_${crypto.randomBytes(24).toString("hex")}`;
}

/** 当前时间在 [start,end] 内且 status=active 的订阅 */
async function findActiveSubscriptionForUser(userId) {
  const now = new Date();
  return baseModel.biz_subscription.findOne({
    where: {
      user_id: userId,
      status: "active",
      start_time: { [op.lte]: now },
      end_time: { [op.gte]: now },
    },
    order: [["id", "DESC"]],
  });
}

async function createToken(body) {
  const { user_id, token_name, expire_at } = body;
  if (!user_id || !expire_at) throw new Error("缺少 user_id 或 expire_at");
  const u = await baseModel.biz_user.findByPk(user_id);
  if (!u) throw new Error("用户不存在");
  if (u.status !== "active") throw new Error("用户已禁用");

  const activeCount = await baseModel.biz_api_token.count({
    where: { user_id, status: "active" },
  });
  if (activeCount >= MAX_TOKENS_PER_USER) {
    throw new Error(`单用户最多 ${MAX_TOKENS_PER_USER} 个有效 Token`);
  }

  const sub = await findActiveSubscriptionForUser(user_id);
  const plan_id = sub ? sub.plan_id : null;

  const plain = generatePlainToken();
  const token_hash = hashPlainToken(plain);

  const row = await baseModel.biz_api_token.create({
    user_id,
    plan_id,
    token_name: token_name || "default",
    token_hash,
    status: "active",
    expire_at,
  });

  return {
    row,
    plain_token: plain,
    warn: sub ? null : "当前无生效中的订阅，鉴权将失败",
  };
}

async function revokeToken(body) {
  const id = body.id;
  if (id == null) throw new Error("缺少 id");
  const row = await baseModel.biz_api_token.findByPk(id);
  if (!row) throw new Error("Token 不存在");
  await row.update({ status: "revoked" });
  return row;
}

async function revokeAllForUser(userId) {
  if (userId == null) throw new Error("缺少 user_id");
  const [n] = await baseModel.biz_api_token.update(
    { status: "revoked" },
    { where: { user_id: userId, status: "active" } }
  );
  return n;
}

module.exports = {
  hashPlainToken,
  createToken,
  revokeToken,
  revokeAllForUser,
  findActiveSubscriptionForUser,
  MAX_TOKENS_PER_USER,
};
