/**
 * Auth API client — login / refresh / logout / whoami / sessions / me
 *
 * Talks to the server-side ``/api/v1/auth/*`` endpoints implemented in
 * ``src/agentkit/server/routes/auth.py`` (U4 — Centralized Auth).
 *
 * U7 refactor:
 *  - ``whoami`` accepts an optional ``refreshToken`` for the cold-start
 *    path (when the access token is gone but a refresh token survives
 *    in the OS Keychain / localStorage fallback).
 *  - ``login`` accepts ``rememberMe`` to ask the server for a 30-day
 *    refresh token TTL.
 *  - New ``listSessions`` / ``revokeSession`` / ``changePassword``
 *    endpoints back the Settings / Security UI (U8).
 */

import { BaseApiClient } from './base'

/** Public user representation returned by the server. */
export interface IAuthUser {
  id: string
  username: string
  email: string
  role: 'member' | 'operator' | 'admin' | string
  is_active: boolean
  is_terminal_authorized: boolean
  is_server_terminal_authorized: boolean
}

/** JWT pair + user info returned by /auth/login and /auth/refresh. */
export interface ITokenPair {
  access_token: string
  refresh_token: string
  token_type: 'bearer'
  expires_in: number
  user: IAuthUser
  /** V2 sessions carry an id; legacy tokens may omit it. */
  session_id?: string
}

/** Public projection of an ``auth_sessions`` row. */
export interface ISessionInfo {
  id: string
  device_fingerprint: string
  device_label: string
  ip: string
  user_agent: string
  auth_provider: string
  created_at: string
  last_active_at: string
  expires_at: string
  is_current: boolean
  /** User id — populated by admin endpoints; user-endpoint omits this. */
  user_id?: string
  /** Revocation flag — admin endpoints surface this for the audit view. */
  revoked?: boolean
  /** Machine-readable revoke reason. ``null`` for active sessions. */
  revoked_reason?: string | null
}

/** Response of /auth/whoami (used for cold-start). */
export interface IWhoamiResponse {
  user: IAuthUser
  access_token: string
  session: ISessionInfo | null
}

class AuthApiClient extends BaseApiClient {
  constructor(baseUrl: string = '/api/v1') {
    super(baseUrl)
  }

  /** Authenticate with username + password. */
  async login(
    username: string,
    password: string,
    rememberMe: boolean = false,
  ): Promise<ITokenPair> {
    return this.request<ITokenPair>('/auth/login', {
      method: 'POST',
      body: JSON.stringify({
        username,
        password,
        remember_me: rememberMe,
      }),
    })
  }

  /** Exchange a refresh token for a new access token. */
  async refresh(refreshToken: string): Promise<ITokenPair> {
    return this.request<ITokenPair>('/auth/refresh', {
      method: 'POST',
      body: JSON.stringify({ refresh_token: refreshToken }),
    })
  }

  /**
   * Cold-start probe.  Returns the current user + a fresh access token
   * + the session metadata.  Used on app boot when only the refresh
   * token is available.
   *
   * The server route accepts both access and refresh tokens (the
   * cold-start case sends a refresh token via a custom header — see
   * ``requestWithToken``).  If you already have an access token, just
   * call ``me()`` instead.
   */
  async whoami(refreshToken?: string): Promise<IWhoamiResponse> {
    if (refreshToken) {
      return this.requestWithToken<{ Authorization: string }, IWhoamiResponse>(
        '/auth/whoami',
        { Authorization: `Bearer ${refreshToken}` },
      )
    }
    return this.request<IWhoamiResponse>('/auth/whoami')
  }

  /** Revoke a refresh token (idempotent). */
  async logout(refreshToken: string): Promise<{ revoked: boolean }> {
    return this.request<{ revoked: boolean }>('/auth/logout', {
      method: 'POST',
      body: JSON.stringify({ refresh_token: refreshToken }),
    })
  }

  /** Fetch the current user's profile (requires Authorization header). */
  async me(): Promise<IAuthUser> {
    return this.request<IAuthUser>('/auth/me')
  }

  // --- Session management (U4 / U8) ---

  /** List the current user's active sessions. */
  async listSessions(): Promise<ISessionInfo[]> {
    return this.request<ISessionInfo[]>('/auth/sessions')
  }

  /** Revoke a single session (own only). */
  async revokeSession(sid: string): Promise<{ revoked: boolean }> {
    return this.request<{ revoked: boolean }>(`/auth/sessions/${encodeURIComponent(sid)}`, {
      method: 'DELETE',
    })
  }

  /** Change the current user's password. Revokes all other sessions. */
  async changePassword(oldPassword: string, newPassword: string): Promise<{ changed: boolean; revoked_other_sessions: number }> {
    return this.request<{ changed: boolean; revoked_other_sessions: number }>(
      '/auth/change-password',
      {
        method: 'POST',
        body: JSON.stringify({
          old_password: oldPassword,
          new_password: newPassword,
        }),
      },
    )
  }
}

export const authApi = new AuthApiClient()
export { AuthApiClient }
