import { env } from '../config/env.js';

// The Admin SDK (src/config/firebase.ts) can create/manage users but cannot
// verify a password — that only exists on Firebase's client SDK or this REST
// API. Our backend calls it directly so /login can accept email+password
// itself. Uses Node's built-in fetch — no extra package needed.
const IDENTITY_TOOLKIT_URL = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword';

export class FirebaseRestError extends Error {
  code: string;

  constructor(code: string) {
    super(code);
    this.code = code;
  }
}

export interface PasswordSignInResult {
  firebaseUid: string;
  idToken: string;
  refreshToken: string;
}

interface IdentityToolkitResponse {
  localId?: string;
  idToken?: string;
  refreshToken?: string;
  error?: { message?: string };
}

export async function signInWithPassword(email: string, password: string): Promise<PasswordSignInResult> {
  const response = await fetch(`${IDENTITY_TOOLKIT_URL}?key=${env.FIREBASE_WEB_API_KEY}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password, returnSecureToken: true }),
  });

  const data = await response.json() as IdentityToolkitResponse;

  if (!response.ok) {
    // Firebase error codes: INVALID_LOGIN_CREDENTIALS, EMAIL_NOT_FOUND,
    // INVALID_PASSWORD, USER_DISABLED, TOO_MANY_ATTEMPTS_TRY_LATER, ...
    throw new FirebaseRestError(data.error?.message ?? 'SIGN_IN_FAILED');
  }

  return { firebaseUid: data.localId!, idToken: data.idToken!, refreshToken: data.refreshToken! };
}

// A refresh token has no expiry (until revoked); the id token it's exchanged
// for expires after 1 hour. Clients without the Firebase client SDK (like
// blenaxis-super-admin, a plain REST consumer) need this to stay signed in
// without asking for a password again — see POST /auth/refresh.
const SECURE_TOKEN_URL = 'https://securetoken.googleapis.com/v1/token';

export interface RefreshResult {
  idToken: string;
  refreshToken: string;
  /** The Firebase uid the tokens belong to. */
  firebaseUid?: string;
}

interface SecureTokenResponse {
  id_token?: string;
  refresh_token?: string;
  user_id?: string;
  error?: { message?: string };
}

export async function refreshIdToken(refreshToken: string): Promise<RefreshResult> {
  const response = await fetch(`${SECURE_TOKEN_URL}?key=${env.FIREBASE_WEB_API_KEY}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: refreshToken }).toString(),
  });

  const data = await response.json() as SecureTokenResponse;

  if (!response.ok) {
    // Firebase error codes: TOKEN_EXPIRED, INVALID_REFRESH_TOKEN, USER_DISABLED, ...
    throw new FirebaseRestError(data.error?.message ?? 'REFRESH_FAILED');
  }

  return { idToken: data.id_token!, refreshToken: data.refresh_token!, firebaseUid: data.user_id };
}
