const crypto = require("crypto");
const Sequelize = require("sequelize");
const op = Sequelize.Op;
const baseModel = require("../../middleware/baseModel");
const biz_token_secret_cipher = require("../utils/biz_token_secret_cipher");
const { normalize_for_write } = require("../utils/query_helpers");

const MAX_TOKENS_PER_USER = 5;

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

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

/** 默认 Token 过期时间：一年后当日 23:59:59 */
function defaultTokenExpireAt() {
  const d = new Date();
  d.setFullYear(d.getFullYear() + 1);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")} 23:59:59`;
}

/** 当前时间在 [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, key } = 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 secret_cipher = biz_token_secret_cipher.encrypt_plain_for_storage(plain);

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

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

/**
 * 管理端编辑：名称、账号 key、过期时间（不改密钥）
 */
async function updateToken(body) {
  const id = body.id;
  if (id == null || id === "") throw new Error("缺少 id");
  const row = await baseModel.biz_api_token.findByPk(id);
  if (!row) throw new Error("Token 不存在");

  const payload = normalize_for_write(
    baseModel.biz_api_token,
    {
      token_name: body.token_name,
      key: body.key,
      expire_at: body.expire_at,
    },
    { for_create: false }
  );
  const patch = {};
  if (payload.token_name !== undefined) patch.token_name = payload.token_name;
  if (payload.key !== undefined) patch.key = payload.key;
  if (payload.expire_at !== undefined) patch.expire_at = payload.expire_at;
  if (Object.keys(patch).length === 0) throw new Error("没有可更新字段");

  await row.update(patch);
  await row.reload();
  return row;
}

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", secret_cipher: null });
  return row;
}

/**
 * 保留同一条 Token 记录，仅更换密钥（旧明文立即失效）
 */
async function regenerateToken(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 不存在");
  if (row.status !== "active") throw new Error("仅可对状态为 active 的 Token 重新生成密钥");

  const u = await baseModel.biz_user.findByPk(row.user_id);
  if (!u) throw new Error("用户不存在");
  if (u.status !== "active") throw new Error("用户已禁用，无法轮换密钥");

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

  const plain = generatePlainToken();
  const token_hash = hashPlainToken(plain);
  const secret_cipher = biz_token_secret_cipher.encrypt_plain_for_storage(plain);

  await row.update({
    token_hash,
    plan_id,
    secret_cipher,
  });
  await row.reload();

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

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

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