/**
 * Auth Client
 *
 * Maneja autenticación, registro, sesiones y tokens
 */

import { AxiosInstance } from 'axios';
import {
  ApiResponse,
  AuthTokens,
  LoginCredentials,
  RegisterData,
  User,
} from '../types';
import { Trading PlatformConfig } from '../client';

export class AuthClient {
  private http: AxiosInstance;
  private config: Trading PlatformConfig;

  public onTokensChanged?: (tokens: AuthTokens | null) => void;

  constructor(http: AxiosInstance, config: Trading PlatformConfig) {
    this.http = http;
    this.config = config;
  }

  /**
   * Login with email and password
   */
  async login(credentials: LoginCredentials): Promise<AuthTokens> {
    const response = await this.http.post<ApiResponse<{ tokens: AuthTokens; user: User }>>(
      '/auth/login',
      credentials
    );
    const tokens = response.data.data.tokens;
    this.onTokensChanged?.(tokens);
    return tokens;
  }

  /**
   * Register new user
   */
  async register(data: RegisterData): Promise<{ user: User; tokens: AuthTokens }> {
    const response = await this.http.post<ApiResponse<{ user: User; tokens: AuthTokens }>>(
      '/auth/register',
      data
    );
    const { tokens } = response.data.data;
    this.onTokensChanged?.(tokens);
    return response.data.data;
  }

  /**
   * Logout current session
   */
  async logout(): Promise<void> {
    await this.http.post('/auth/logout');
    this.onTokensChanged?.(null);
  }

  /**
   * Refresh access token
   */
  async refreshToken(refreshToken: string): Promise<AuthTokens> {
    const response = await this.http.post<ApiResponse<AuthTokens>>(
      '/auth/refresh',
      { refreshToken }
    );
    const tokens = response.data.data;
    this.onTokensChanged?.(tokens);
    return tokens;
  }

  /**
   * Get current user profile
   */
  async getCurrentUser(): Promise<User> {
    const response = await this.http.get<ApiResponse<User>>('/auth/me');
    return response.data.data;
  }

  /**
   * Update user profile
   */
  async updateProfile(data: Partial<User>): Promise<User> {
    const response = await this.http.patch<ApiResponse<User>>('/auth/profile', data);
    return response.data.data;
  }

  /**
   * Change password
   */
  async changePassword(currentPassword: string, newPassword: string): Promise<void> {
    await this.http.post('/auth/change-password', {
      currentPassword,
      newPassword,
    });
  }

  /**
   * Request password reset
   */
  async requestPasswordReset(email: string): Promise<void> {
    await this.http.post('/auth/forgot-password', { email });
  }

  /**
   * Reset password with token
   */
  async resetPassword(token: string, newPassword: string): Promise<void> {
    await this.http.post('/auth/reset-password', { token, newPassword });
  }

  /**
   * Verify email
   */
  async verifyEmail(token: string): Promise<void> {
    await this.http.post('/auth/verify-email', { token });
  }

  /**
   * Resend verification email
   */
  async resendVerificationEmail(): Promise<void> {
    await this.http.post('/auth/resend-verification');
  }

  /**
   * Enable 2FA
   */
  async enable2FA(): Promise<{ secret: string; qrCode: string }> {
    const response = await this.http.post<ApiResponse<{ secret: string; qrCode: string }>>(
      '/auth/2fa/enable'
    );
    return response.data.data;
  }

  /**
   * Verify and activate 2FA
   */
  async verify2FA(code: string): Promise<{ backupCodes: string[] }> {
    const response = await this.http.post<ApiResponse<{ backupCodes: string[] }>>(
      '/auth/2fa/verify',
      { code }
    );
    return response.data.data;
  }

  /**
   * Disable 2FA
   */
  async disable2FA(code: string): Promise<void> {
    await this.http.post('/auth/2fa/disable', { code });
  }

  /**
   * OAuth login - get redirect URL
   */
  getOAuthUrl(provider: 'google' | 'facebook' | 'apple' | 'github'): string {
    return `${this.config.baseUrl}/auth/oauth/${provider}`;
  }

  /**
   * Get active sessions
   */
  async getSessions(): Promise<Array<{
    id: string;
    device: string;
    ip: string;
    lastActive: string;
    current: boolean;
  }>> {
    const response = await this.http.get<ApiResponse<any[]>>('/auth/sessions');
    return response.data.data;
  }

  /**
   * Revoke a session
   */
  async revokeSession(sessionId: string): Promise<void> {
    await this.http.delete(`/auth/sessions/${sessionId}`);
  }

  /**
   * Revoke all other sessions
   */
  async revokeAllSessions(): Promise<void> {
    await this.http.post('/auth/sessions/revoke-all');
  }
}
