/**
 * Typed errors for the auth layer. Callers branch on `code` so commands
 * can map specific failures to friendly UX without parsing messages.
 */

export type AuthErrorCode =
  | "NOT_CONFIGURED"
  | "INVALID_STORE"
  | "API_ERROR"
  | "UNAUTHENTICATED"
  | "OAUTH_NOT_CONFIGURED"
  | "REFRESH_FAILED";

export class AuthError extends Error {
  readonly code: AuthErrorCode;
  readonly hint?: string;

  constructor(code: AuthErrorCode, message: string, hint?: string) {
    super(message);
    this.name = "AuthError";
    this.code = code;
    this.hint = hint;
  }
}

export const ErrNotConfigured = () =>
  new AuthError(
    "NOT_CONFIGURED",
    "No HeyGen credentials found",
    "Run `hyperframes auth login` to sign in.",
  );

export const ErrInvalidStore = (detail: string) =>
  new AuthError(
    "INVALID_STORE",
    `Credential file is unreadable: ${detail}`,
    "Delete ~/.heygen/credentials and run `hyperframes auth login` to re-create it.",
  );

export const ErrUnauthenticated = (detail?: string) =>
  new AuthError(
    "UNAUTHENTICATED",
    detail ? `HeyGen rejected the credential: ${detail}` : "HeyGen rejected the credential",
    "Run `hyperframes auth login` to re-authenticate.",
  );

export const ErrApi = (status: number, detail: string) =>
  new AuthError("API_ERROR", `HeyGen API error (${status}): ${detail}`);

export const ErrOAuthNotConfigured = () =>
  new AuthError(
    "OAUTH_NOT_CONFIGURED",
    "OAuth client is not configured",
    "Set HYPERFRAMES_OAUTH_CLIENT_ID, or run `hyperframes auth login --api-key`.",
  );

export const ErrRefreshFailed = (detail?: string) =>
  new AuthError(
    "REFRESH_FAILED",
    detail ? `Failed to refresh OAuth tokens: ${detail}` : "Failed to refresh OAuth tokens",
    "Run `hyperframes auth login` to re-authenticate.",
  );

export function isAuthError(err: unknown): err is AuthError {
  return err instanceof AuthError;
}
