import type { AuthContext } from "@/lib/auth/types";
import { getDevUser, isDevAuthEnabled } from "@/lib/auth/devUser";
import { isConvexEnabled } from "@/lib/convex/enabled";
import { convexAuthNextjsToken } from "@convex-dev/auth/nextjs/server";
import { fetchQuery } from "convex/nextjs";
import { api } from "@/lib/convex/api";

export class HttpError extends Error {
  status: number;

  constructor(status: number, message: string) {
    super(message);
    this.name = "HttpError";
    this.status = status;
  }
}

/**
 * 获取认证上下文
 *
 * 优先级：
 * 1. Convex Auth（如果启用）- 服务端：从 Convex Auth cookies 获取并查询当前用户；客户端：从 hooks 获取
 * 2. 开发用户（如果启用）
 * 3. 抛出错误（未配置）
 */
export async function getAuthContext(): Promise<AuthContext> {
  // 1. 检查是否启用 Convex Auth
  if (isConvexEnabled()) {
    // 说明：开发模式下允许使用固定用户快速跑通链路（例如迁移测试）。
    if (isDevAuthEnabled()) {
      return getDevUser();
    }

    const token = await convexAuthNextjsToken();
    if (!token) {
      throw new Error("未登录，请先登录");
    }

    // 说明：从 Convex Auth token 获取当前用户（users 表由 authTables 提供）。
    // 这里不强依赖具体字段结构，避免升级 authTables 后类型不兼容。
    const user = (await fetchQuery(api.users.currentUser, {}, { token })) as unknown;
    if (!user || typeof user !== "object") {
      throw new Error("未登录，请先登录");
    }

    const record = user as Record<string, unknown>;
    const id = record["_id"];
    const email = record["email"];
    const name = record["name"];

    if (typeof id !== "string" || !id) {
      throw new Error("未登录，请先登录");
    }

    return {
      userId: id,
      email: typeof email === "string" ? email : undefined,
      name: typeof name === "string" ? name : undefined,
    };
  }

  // 2. 检查是否启用开发用户模式
  if (isDevAuthEnabled()) {
    return getDevUser();
  }

  // 3. 未配置认证
  throw new Error("Auth is not configured");
}

/**
 * 要求已认证的上下文
 *
 * 如果未认证，抛出 401 错误
 */
export async function requireAuthContext(): Promise<AuthContext> {
  try {
    return await getAuthContext();
  } catch (err) {
    const message = err instanceof Error ? err.message : "Unauthorized";
    throw new HttpError(401, message);
  }
}

/**
 * 获取当前用户 ID
 *
 * 用于服务端组件和 API 路由
 */
export async function getCurrentUserId(): Promise<string> {
  const auth = await requireAuthContext();
  return auth.userId;
}
