import { NextRequest, NextResponse } from "next/server";
import { Prisma } from "@prisma/client";
import { prisma } from "@/lib/prisma";

export class ApiError extends Error {
  constructor(
    message: string,
    public status: number = 400,
  ) {
    super(message);
    this.name = "ApiError";
  }
}

/** Validates that value is a non-empty string; throws 401 otherwise. */
export function requireUserId(value: unknown): string {
  if (!value || typeof value !== "string") {
    throw new ApiError("请先登录", 401);
  }
  return value;
}

/** Finds user by ID; throws 404 if not found. */
export async function requireUser(userId: string) {
  const user = await prisma.user.findUnique({ where: { id: userId } });
  if (!user) throw new ApiError("用户不存在", 404);
  return user;
}

type RouteContext = { params: Promise<Record<string, string>> };

type RouteHandler = (
  req: NextRequest,
  ctx: RouteContext,
) => Promise<NextResponse>;

/**
 * Wraps a Next.js route handler with unified error handling.
 * - ApiError instances are converted to JSON responses with matching status codes
 * - Unknown errors are logged and returned as 500
 */
export function apiHandler(handler: RouteHandler): RouteHandler {
  return async (req, ctx) => {
    try {
      return await handler(req, ctx);
    } catch (e) {
      if (e instanceof ApiError) {
        return NextResponse.json({ error: e.message }, { status: e.status });
      }
      if (
        e instanceof Prisma.PrismaClientKnownRequestError &&
        e.code === "P2002"
      ) {
        return NextResponse.json(
          { error: "该记录已存在或值已被占用" },
          { status: 409 },
        );
      }
      console.error(`[API ${req.method} ${req.nextUrl.pathname}]`, e);
      return NextResponse.json({ error: "操作失败" }, { status: 500 });
    }
  };
}
