import { apiClient } from '@/services/api/client';
import axios, { AxiosError } from 'axios';
import type {
  LoginFormData,
  RegisterFormData,
  ForgotPasswordFormData,
  ResetPasswordFormData,
} from '../types';

export interface AuthResponse {
  user: {
    id: number;
    email: string;
    username?: string;
  };
  token: {
    access_token: string;
    refresh_token: string;
    expires_in: number;
  };
}

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

/**
 * Gère les erreurs API de manière standardisée
 */
function handleApiError(error: unknown): never {
  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 ||
        'An error occurred';

      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;
}

/**
 * Authentifie un utilisateur avec email et mot de passe
 * @param data - Données de connexion (email, password)
 * @returns Promise avec les tokens et les informations utilisateur
 * @throws ApiError en cas d'erreur
 */
export async function login(data: LoginFormData): Promise<AuthResponse> {
  try {
    const response = await apiClient.post<AuthResponse>('/auth/login', data);
    return response.data;
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Enregistre un nouvel utilisateur
 * @param data - Données d'inscription (email, password, username)
 * @returns Promise avec les tokens et les informations utilisateur
 * @throws ApiError en cas d'erreur
 */
export async function register(data: RegisterFormData): Promise<AuthResponse> {
  try {
    const response = await apiClient.post<AuthResponse>('/auth/register', {
      email: data.email,
      password: data.password,
      password_confirm: data.confirmPassword, // Envoyer la confirmation du mot de passe
      username: data.username,
    });
    return response.data;
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Déconnecte l'utilisateur actuel
 * @throws ApiError en cas d'erreur
 */
export async function logout(): Promise<void> {
  try {
    await apiClient.post('/auth/logout');
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Rafraîchit le token d'accès avec un refresh token
 * @param refreshToken - Le refresh token
 * @returns Promise avec les nouveaux tokens et les informations utilisateur
 * @throws ApiError en cas d'erreur
 */
export async function refreshToken(refreshToken: string): Promise<AuthResponse> {
  try {
    const response = await apiClient.post<AuthResponse>('/auth/refresh', {
      refreshToken,
    });
    return response.data;
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Demande une réinitialisation de mot de passe
 * @param data - Données contenant l'email
 * @throws ApiError en cas d'erreur
 */
export async function requestPasswordReset(
  data: ForgotPasswordFormData
): Promise<void> {
  try {
    await apiClient.post('/auth/password/reset-request', data);
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Réinitialise le mot de passe avec un token
 * @param data - Données contenant le token et le nouveau mot de passe
 * @throws ApiError en cas d'erreur
 */
export async function resetPassword(data: ResetPasswordFormData): Promise<void> {
  try {
    await apiClient.post('/auth/password/reset', {
      token: data.token,
      password: data.password,
    });
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Vérifie l'email avec un token de vérification
 * @param token - Token de vérification
 * @throws ApiError en cas d'erreur
 */
export async function verifyEmail(token: string): Promise<void> {
  try {
    await apiClient.get(`/auth/verify-email?token=${token}`);
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Renvoie l'email de vérification
 * @param email - Email de l'utilisateur
 * @throws ApiError en cas d'erreur
 */
export async function resendVerificationEmail(email: string): Promise<void> {
  try {
    await apiClient.post('/auth/resend-verification', { email });
  } catch (error) {
    return handleApiError(error);
  }
}

/**
 * Vérifie la disponibilité d'un nom d'utilisateur
 * @param username - Le nom d'utilisateur à vérifier
 * @returns Promise avec true si disponible, false sinon
 * @throws ApiError en cas d'erreur
 */
export async function checkUsernameAvailability(username: string): Promise<boolean> {
  try {
    const response = await apiClient.get<{ available: boolean }>(`/auth/check-username?username=${encodeURIComponent(username)}`);
    return response.data.available;
  } catch (error) {
    return handleApiError(error);
  }
}

