import { Router } from "express";
import { z } from "zod";
import { prisma } from "@stamp/shared";
import { requireAuth } from "../middleware/auth.js";

const router = Router();

const redeemSchema = z.object({
  stampId: z.string().uuid("图章 ID 格式不正确"),
});

router.post("/redeem", requireAuth, async (req, res) => {
  const parsed = redeemSchema.safeParse(req.body);
  if (!parsed.success) {
    res.status(400).json({ success: false, error: { code: "VALIDATION", message: parsed.error.issues[0].message } });
    return;
  }

  const { stampId } = parsed.data;
  const userId = req.userId!;

  try {
    const redemption = await prisma.$transaction(async (tx) => {
      const collection = await tx.collection.findUnique({
        where: { userId_stampId: { userId, stampId } },
      });
      if (!collection) {
        throw new RedeemError("NOT_COLLECTED", "你还没有收集这枚图章", 400);
      }

      const already = await tx.redemption.findUnique({
        where: { userId_stampId: { userId, stampId } },
      });
      if (already) {
        throw new RedeemError("ALREADY_REDEEMED", "你已经兑换过这枚图章对应的奖品", 409);
      }

      const prize = await tx.prize.findUnique({ where: { stampId } });
      if (!prize || !prize.enabled) {
        throw new RedeemError("PRIZE_UNAVAILABLE", "该图章暂无可兑换的奖品", 400);
      }

      const decremented = await tx.prize.updateMany({
        where: { id: prize.id, stock: { gt: 0 } },
        data: { stock: { decrement: 1 } },
      });
      if (decremented.count === 0) {
        throw new RedeemError("OUT_OF_STOCK", "奖品已兑完", 400);
      }

      return tx.redemption.create({
        data: {
          userId,
          stampId,
          prizeId: prize.id,
          prizeName: prize.name,
        },
        include: { stamp: { select: { name: true } } },
      });
    });

    res.json({
      success: true,
      data: {
        id: redemption.id,
        stampId: redemption.stampId,
        stampName: redemption.stamp.name,
        prizeName: redemption.prizeName,
        redeemedAt: redemption.redeemedAt.toISOString(),
      },
    });
  } catch (e) {
    if (e instanceof RedeemError) {
      res.status(e.status).json({ success: false, error: { code: e.code, message: e.message } });
      return;
    }
    throw e;
  }
});

router.get("/history", requireAuth, async (req, res) => {
  const records = await prisma.redemption.findMany({
    where: { userId: req.userId! },
    include: { stamp: { select: { name: true } } },
    orderBy: { redeemedAt: "desc" },
  });

  const data = records.map((r) => ({
    id: r.id,
    stampId: r.stampId,
    stampName: r.stamp.name,
    prizeName: r.prizeName,
    redeemedAt: r.redeemedAt.toISOString(),
  }));

  res.json({ success: true, data });
});

class RedeemError extends Error {
  constructor(
    public code: string,
    message: string,
    public status: number,
  ) {
    super(message);
  }
}

export default router;
