import type { SupportedLocale } from '../i18n/types.js';
import type { AppSupabaseClient } from '../supabase/client.js';

export interface SignupParams {
  email: string;
  // Login handle. Stored with original casing but uniqueness is case-insensitive
  // (citext). Must match ^[A-Za-z0-9_]{3,32}$.
  username: string;
  // Optional human-readable name. Defaults to username server-side if omitted.
  displayName?: string;
  // Invite code is mandatory (enforced by the handle_new_user trigger).
  inviteCode: string;
  // Deep link the magic-link email should bounce back to.
  // e.g. `chatapp://auth/callback` on mobile, `http://localhost:1420/auth/callback` on desktop dev.
  redirectTo: string;
  // Optional initial locale for the profile row. Defaults to 'en' server-side.
  locale?: SupportedLocale;
}

// Trigger signup. User receives a magic link email. Completion happens in
// `completeSessionFromUrl` below once the callback fires.
export async function signUpWithMagicLink(
  client: AppSupabaseClient,
  params: SignupParams,
): Promise<void> {
  const { error } = await client.auth.signInWithOtp({
    email: params.email,
    options: {
      emailRedirectTo: params.redirectTo,
      shouldCreateUser: true,
      data: {
        invite_code: params.inviteCode,
        // Preserve case. `profiles.username` is citext so uniqueness + lookups
        // stay case-insensitive regardless of stored casing.
        username: params.username.trim(),
        display_name: params.displayName ?? params.username,
        ...(params.locale ? { locale: params.locale } : {}),
      },
    },
  });
  if (error) throw error;
}

// Trigger magic-link login for an existing user. No invite code needed.
export async function loginWithMagicLink(
  client: AppSupabaseClient,
  email: string,
  redirectTo: string,
): Promise<void> {
  const { error } = await client.auth.signInWithOtp({
    email,
    options: {
      emailRedirectTo: redirectTo,
      shouldCreateUser: false,
    },
  });
  if (error) throw error;
}

// Parse a callback URL produced by the magic-link email and establish a session.
// Works for both PKCE (`?code=…`) and legacy token-hash (`#access_token=…`).
export async function completeSessionFromUrl(
  client: AppSupabaseClient,
  url: string,
): Promise<void> {
  const u = new URL(url);

  // PKCE flow: exchange the code.
  const code = u.searchParams.get('code');
  if (code) {
    const { error } = await client.auth.exchangeCodeForSession(code);
    if (error) throw error;
    return;
  }

  // Hash fragment flow.
  if (u.hash && u.hash.length > 1) {
    const hash = new URLSearchParams(u.hash.slice(1));
    const access_token = hash.get('access_token');
    const refresh_token = hash.get('refresh_token');
    if (access_token && refresh_token) {
      const { error } = await client.auth.setSession({ access_token, refresh_token });
      if (error) throw error;
      return;
    }
  }

  throw new Error('callback URL contained no auth params');
}

export async function signOut(client: AppSupabaseClient): Promise<void> {
  // `scope: 'local'` only ends the session in THIS client. Without it Supabase
  // defaults to 'global', which invalidates the user's refresh tokens
  // everywhere — meaning a logout in the browser would also kick the desktop
  // app (and vice versa) the next time it tries to refresh its token.
  const { error } = await client.auth.signOut({ scope: 'local' });
  if (error) throw error;
}

// Verify a 6-digit OTP that arrived via magic-link email. Establishes a
// session in the CURRENT webview — no browser redirect involved. Used by the
// desktop/mobile apps where cross-origin redirects don't carry the session
// back to the native webview.
export async function verifyMagicLinkOtp(
  client: AppSupabaseClient,
  email: string,
  token: string,
): Promise<void> {
  const { error } = await client.auth.verifyOtp({
    email,
    token: token.trim(),
    type: 'email',
  });
  if (error) throw error;
}
