// 后端投票规则验证(不污染生产数据,所有写操作都在事务里 rollback)
import { PrismaClient, Prisma } from "@prisma/client";
const prisma = new PrismaClient({ log: ["error"] });

const PASS = "\x1b[32mPASS\x1b[0m";
const FAIL = "\x1b[31mFAIL\x1b[0m";

let results = [];
function record(name, ok, detail = "") {
  results.push({ name, ok, detail });
  console.log(`  [${ok ? PASS : FAIL}] ${name}${detail ? "  -- " + detail : ""}`);
}

async function main() {
  console.log("=== 后端投票规则验证(事务回滚,不留痕)===\n");

  // 取一个真实用户(测试数据中的最大投票用户)
  const sample = await prisma.$queryRaw`
    SELECT user_id, COUNT(*) AS c FROM votes GROUP BY user_id ORDER BY c DESC LIMIT 1
  `;
  if (sample.length === 0) {
    console.log("[note] votes 表为空,跳过有交互的测试");
    return;
  }
  const sampleUserId = BigInt(sample[0].user_id);
  const sampleVotes = await prisma.vote.findMany({
    where: { userId: sampleUserId },
    select: { artistId: true },
  });
  const sampleArtist = sampleVotes[0].artistId;
  console.log(
    `测试样本:user=${sampleUserId} 已投艺人=[${sampleVotes
      .map((v) => v.artistId)
      .join(",")}]\n`,
  );

  // 测试 1:DB unique 约束生效 —— 重复 (userId, artistId) INSERT 应失败 P2002
  console.log("[测试 1] DB unique 约束:重复 (userId, artistId) 必被拒");
  try {
    await prisma.$transaction(
      async (tx) => {
        await tx.vote.create({
          data: {
            userId: sampleUserId,
            artistId: sampleArtist,
            count: 1,
            source: "QUOTA",
          },
        });
        throw new Error("ROLLBACK_AFTER_TEST"); // 强制回滚
      },
      { timeout: 10000 },
    );
    record("unique 约束阻挡重复投票", false, "INSERT 居然成功了");
  } catch (e) {
    if (
      e instanceof Prisma.PrismaClientKnownRequestError &&
      e.code === "P2002"
    ) {
      record("unique 约束阻挡重复投票", true, "P2002 unique constraint");
    } else if (e.message === "ROLLBACK_AFTER_TEST") {
      record(
        "unique 约束阻挡重复投票",
        false,
        "INSERT 居然成功 = 没有 unique 约束!",
      );
    } else {
      record("unique 约束阻挡重复投票", false, `异常: ${e.message}`);
    }
  }

  // 测试 2:不同艺人 INSERT 应该成功(在事务内回滚,不留痕)
  console.log(
    "\n[测试 2] 不同艺人投票不会被 unique 阻挡(事务内验证后回滚)",
  );
  const candidateArtist = await prisma.artist.findFirst({
    where: {
      id: { notIn: sampleVotes.map((v) => v.artistId) },
      status: "ACTIVE",
    },
    select: { id: true },
  });
  if (!candidateArtist) {
    record("跨艺人投票", false, "找不到该用户未投过的艺人样本");
  } else {
    try {
      await prisma.$transaction(
        async (tx) => {
          await tx.vote.create({
            data: {
              userId: sampleUserId,
              artistId: candidateArtist.id,
              count: 1,
              source: "QUOTA",
            },
          });
          throw new Error("ROLLBACK_AFTER_TEST");
        },
        { timeout: 10000 },
      );
      record("跨艺人投票", false, "事务未回滚");
    } catch (e) {
      if (e.message === "ROLLBACK_AFTER_TEST") {
        record(
          "跨艺人投票",
          true,
          `允许投给新艺人 ${candidateArtist.id},事务已回滚`,
        );
      } else {
        record("跨艺人投票", false, `异常: ${e.message}`);
      }
    }
  }

  // 测试 3:终身额度 12 票上限(由 /api/vote 应用层校验,DB 不强制)
  //   验证:对所有用户跑 SELECT COUNT(*) < 12 是 true,确认目前没人超额
  console.log("\n[测试 3] 终身额度上限 12 票 - 数据合规性");
  const overflows = await prisma.$queryRaw`
    SELECT user_id, COUNT(*) AS c FROM votes GROUP BY user_id HAVING c > 12
  `;
  if (overflows.length === 0) {
    record(
      "现存数据无超额用户",
      true,
      "12 票上限对所有现存用户都成立(应用层会兜底)",
    );
  } else {
    record(
      "现存数据无超额用户",
      false,
      `${overflows.length} 个用户已超过 12 票:${overflows
        .map((r) => `user=${r.user_id} c=${r.c}`)
        .join("; ")}`,
    );
  }

  // 测试 4:回归确认 /api/me 用的 vote 关键查询能返回 votedArtists 列表
  console.log("\n[测试 4] /api/me votedArtists 查询正确性");
  const votedList = await prisma.vote.findMany({
    where: { userId: sampleUserId },
    select: { artistId: true, createdAt: true },
    orderBy: { createdAt: "asc" },
  });
  const isAsc = votedList.every(
    (v, i) =>
      i === 0 || votedList[i - 1].createdAt.getTime() <= v.createdAt.getTime(),
  );
  record(
    "votedArtists 按 createdAt 升序",
    isAsc,
    `共 ${votedList.length} 条`,
  );

  // 测试 5:旧 daily_quota / fan_supports 数据仍可读(向后兼容,不报错)
  console.log("\n[测试 5] 旧数据兼容性");
  try {
    const dqCount = await prisma.dailyQuota.count();
    const fsCount = await prisma.fanSupport.count();
    record("旧 DailyQuota / FanSupport 仍可读", true, `dq=${dqCount} fs=${fsCount}`);
  } catch (e) {
    record("旧 DailyQuota / FanSupport 仍可读", false, e.message);
  }

  // 汇总
  console.log("\n=== 汇总 ===");
  const passed = results.filter((r) => r.ok).length;
  const failed = results.length - passed;
  console.log(`通过 ${passed} / 共 ${results.length}${failed ? `  失败 ${failed}` : ""}`);
  await prisma.$disconnect();
  if (failed) process.exit(1);
}

main().catch(async (e) => {
  console.error("\n[ABORT]", e);
  await prisma.$disconnect();
  process.exit(1);
});
