import type { Context } from "@wrnexus/core";
import type { AuthEngine } from "./engine.ts";
import type { AuthSession, AuthUser } from "./types.ts";

export type AuthRouteName =
  | "signIn"
  | "signUp"
  | "signOut"
  | "forgotPassword"
  | "resetPassword"
  | "verifyEmail"
  | "verifyPhone"
  | "twoFactor"
  | "sessions"
  | "passkeys";

const DEFAULT_AUTH_ROUTES: Record<AuthRouteName, string> = {
  signIn: "/sign-in",
  signUp: "/sign-up",
  signOut: "/api/auth/logout",
  forgotPassword: "/forgot-password",
  resetPassword: "/reset-password",
  verifyEmail: "/verify-email",
  verifyPhone: "/verify-phone",
  twoFactor: "/two-factor",
  sessions: "/account/sessions",
  passkeys: "/account/passkeys",
};

export function authRoute(
  name: AuthRouteName,
  options: { basePath?: string; overrides?: Partial<Record<AuthRouteName, string>> } = {},
): string {
  const route = options.overrides?.[name] ?? DEFAULT_AUTH_ROUTES[name];
  if (!options.basePath || route.startsWith("http://") || route.startsWith("https://"))
    return route;
  return `${options.basePath.replace(/\/$/, "")}/${route.replace(/^\//, "")}`;
}

export function authSuccess<T extends Record<string, unknown>>(
  data: T,
  init: ResponseInit = {},
): Response {
  return Response.json({ ok: true, ...data }, { status: init.status ?? 200, ...init });
}

export function authFailure(
  code: string,
  message: string,
  status = 400,
  details?: Record<string, unknown>,
): Response {
  return Response.json(
    { ok: false, error: { code, message, ...(details ? { details } : {}) } },
    { status },
  );
}

export function requireAuthUser(ctx: Context): AuthUser {
  if (!ctx.user || typeof ctx.user !== "object") {
    throw new Response("Unauthorized", { status: 401 });
  }
  return ctx.user as AuthUser;
}

export function optionalAuthUser(ctx: Context): AuthUser | null {
  return ctx.user && typeof ctx.user === "object" ? (ctx.user as AuthUser) : null;
}

export async function currentAuthSession(
  engine: AuthEngine,
  sessionId: string | undefined,
): Promise<AuthSession | null> {
  if (!sessionId) return null;
  const session = await engine.store.findSession(sessionId);
  return session ?? null;
}

export function authComponentProps(
  input: Record<string, unknown>,
  defaults: { color?: string; size?: string; class?: string } = {},
): Record<string, unknown> {
  return {
    color: defaults.color ?? "primary",
    size: defaults.size ?? "md",
    class: defaults.class ?? "",
    ...input,
  };
}
