import axios, { AxiosError } from 'axios';
import { TokenStorage } from '../tokenStorage';

// T0177: Re-export apiClient from client.ts which has interceptors for automatic token refresh
export { apiClient } from './client';

export interface RegisterRequest {
  email: string;
  password: string;
  password_confirm: string;
}

export interface LoginRequest {
  email: string;
  password: string;
  remember_me?: boolean;
}

export interface RegisterResponse {
  user: {
    id: number;
    email: string;
  };
  token: {
    access_token: string;
    refresh_token: string;
    expires_in: number;
  };
}

export interface LoginResponse {
  user: {
    id: number;
    email: string;
  };
  token: {
    access_token: string;
    refresh_token: string;
    expires_in: number;
  };
}

export interface ApiError {
  message: string;
  code?: string;
  details?: Record<string, unknown>;
}

/**
 * Enregistre un nouvel utilisateur
 * @param data - Données d'inscription (email, password, password_confirm)
 * @returns Promise avec la réponse contenant l'utilisateur et les tokens
 * @throws ApiError en cas d'erreur
 */
export async function register(data: RegisterRequest): Promise<RegisterResponse> {
  try {
    const response = await apiClient.post<RegisterResponse>('/auth/register', {
      email: data.email,
      password: data.password,
      password_confirm: data.password_confirm,
    });
    
    // Stocker les tokens dans localStorage
    if (response.data.token) {
      localStorage.setItem('access_token', response.data.token.access_token);
      localStorage.setItem('refresh_token', response.data.token.refresh_token);
    }
    
    return response.data;
  } catch (error) {
    // Gérer les erreurs API
    if (axios.isAxiosError(error)) {
      const axiosError = error as AxiosError<{ error?: string; message?: string }>;
      
      if (axiosError.response) {
        // Erreur de réponse du serveur
        const errorMessage = 
          axiosError.response.data?.error || 
          axiosError.response.data?.message || 
          'Registration failed';
        
        const apiError: ApiError = {
          message: errorMessage,
          code: axiosError.response.status.toString(),
          details: axiosError.response.data as Record<string, unknown>,
        };
        
        throw apiError;
      } else if (axiosError.request) {
        // Requête envoyée mais pas de réponse
        throw {
          message: 'Network error: Unable to connect to server',
          code: 'NETWORK_ERROR',
        } as ApiError;
      }
    }
    
    // Erreur inconnue
    throw {
      message: error instanceof Error ? error.message : 'An unexpected error occurred',
      code: 'UNKNOWN_ERROR',
    } as ApiError;
  }
}

/**
 * Connecte un utilisateur existant
 * T0167: Inclut le flag remember_me pour étendre la durée du refresh token
 * @param data - Données de connexion (email, password, remember_me)
 * @returns Promise avec la réponse contenant l'utilisateur et les tokens
 * @throws ApiError en cas d'erreur
 */
export async function login(data: LoginRequest): Promise<LoginResponse> {
  try {
    const response = await apiClient.post<LoginResponse>('/auth/login', {
      email: data.email,
      password: data.password,
      remember_me: data.remember_me || false,
    });
    
    // Stocker les tokens dans localStorage
    // T0167: Le backend gère déjà l'expiration selon remember_me (30 ou 90 jours)
    if (response.data.token) {
      localStorage.setItem('access_token', response.data.token.access_token);
      localStorage.setItem('refresh_token', response.data.token.refresh_token);
      // Stocker le flag remember_me pour référence future
      if (data.remember_me) {
        localStorage.setItem('remember_me', 'true');
      } else {
        localStorage.removeItem('remember_me');
      }
    }
    
    return response.data;
  } catch (error) {
    // Gérer les erreurs API
    if (axios.isAxiosError(error)) {
      const axiosError = error as AxiosError<{ error?: string; message?: string }>;
      
      if (axiosError.response) {
        // Erreur de réponse du serveur
        const errorMessage = 
          axiosError.response.data?.error || 
          axiosError.response.data?.message || 
          'Login failed';
        
        const apiError: ApiError = {
          message: errorMessage,
          code: axiosError.response.status.toString(),
          details: axiosError.response.data as Record<string, unknown>,
        };
        
        throw apiError;
      } else if (axiosError.request) {
        // Requête envoyée mais pas de réponse
        throw {
          message: 'Network error: Unable to connect to server',
          code: 'NETWORK_ERROR',
        } as ApiError;
      }
    }
    
    // Erreur inconnue
    throw {
      message: error instanceof Error ? error.message : 'An unexpected error occurred',
      code: 'UNKNOWN_ERROR',
    } as ApiError;
  }
}



/**
 * Déconnecte l'utilisateur
 * T0179: Appelle l'endpoint POST /api/v1/auth/logout et supprime les tokens
 * @returns Promise qui se résout quand le logout est terminé
 */
export async function logout(): Promise<void> {
  try {
    // T0179: Appeler endpoint POST /api/v1/auth/logout
    await apiClient.post('/auth/logout');
  } catch (error) {
    // T0179: Même en cas d'erreur, on supprime les tokens localement
    // pour éviter que l'utilisateur reste bloqué
    console.warn('Logout API call failed, but tokens will be cleared locally:', error);
  } finally {
    // T0179: Supprimer tokens du storage
    TokenStorage.clearTokens();
  }
}
