import { auth } from "@/auth";
import { NextResponse } from "next/server";
import type { Session } from "next-auth";
import { type Action, PermissionError, can } from "@/lib/permissions";

export class ApiAuthError extends Error {
  constructor(message = "Unauthorized") {
    super(message);
    this.name = "ApiAuthError";
  }
}

export type OrgSession = Session & {
  user: Session["user"] & { id: string; orgId: string };
};

export async function requireApiAuth(): Promise<Session> {
  const session = await auth();
  if (!session?.user?.id) {
    throw new ApiAuthError();
  }
  return session;
}

export async function requireApiAuthWithOrg(
  action?: Action
): Promise<OrgSession> {
  const session = await auth();
  if (!session?.user?.id || !session.user.orgId) {
    throw new ApiAuthError();
  }
  if (action && !can(session.user.role, action)) {
    throw new PermissionError(`Missing permission: ${action}`, action);
  }
  return session as OrgSession;
}

/**
 * Shorthand for routes that require an authenticated org member with a
 * specific permission. Always throws; callers should wrap with
 * handleApiError so the correct HTTP status is returned.
 */
export async function requireApiAuthWithPermission(
  action: Action
): Promise<OrgSession> {
  return requireApiAuthWithOrg(action);
}

export function handleApiError(error: unknown) {
  if (error instanceof ApiAuthError) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  if (error instanceof PermissionError) {
    return NextResponse.json(
      { error: error.message, action: error.action },
      { status: 403 }
    );
  }
  console.error("[API Error]", error);
  return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
