import { apiClient } from '@/services/api/client';
import { requireFeature } from '@/config/features';
import { Role, AssignRoleRequest } from '../types/role';
import { AxiosError } from 'axios';

/**
 * Role Service
 * FE-API-011: Service frontend pour gérer les rôles et permissions
 *
 * Backend endpoints are implemented:
 * - GET /api/v1/roles - Get all roles
 * - GET /api/v1/roles/:id - Get role by ID
 * - POST /api/v1/roles - Create role
 * - PUT /api/v1/roles/:id - Update role
 * - DELETE /api/v1/roles/:id - Delete role
 * - GET /api/v1/users/:userId/roles - Get user roles
 * - POST /api/v1/users/:userId/roles - Assign role to user
 * - DELETE /api/v1/users/:userId/roles/:roleId - Revoke role from user
 *
 * @see FEATURES.ROLE_MANAGEMENT
 */

/**
 * Récupère tous les rôles
 * @returns Liste des rôles
 * @throws Error si la requête échoue
 */
export async function getRoles(): Promise<Role[]> {
  try {
    // Backend returns { success: true, data: Role[] }
    // apiClient unwraps to Role[] directly
    const response = await apiClient.get<Role[]>('/roles');
    return Array.isArray(response.data) ? response.data : [];
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to access roles');
      }
      if (error.response?.status === 403) {
        throw new Error('Forbidden: You do not have permission to view roles');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to fetch roles';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Récupère un rôle par son ID
 * @param roleId ID du rôle
 * @returns Le rôle
 * @throws Error si la requête échoue
 */
export async function getRole(roleId: string): Promise<Role> {
  try {
    // Backend returns { success: true, data: Role }
    // apiClient unwraps to Role directly
    const response = await apiClient.get<Role>(`/roles/${roleId}`);
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to access role');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to view this role',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('Role not found');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to fetch role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Récupère tous les rôles d'un utilisateur
 * @param userId ID de l'utilisateur
 * @returns Liste des rôles de l'utilisateur
 * @throws Error si la requête échoue
 */
export async function getUserRoles(userId: string): Promise<Role[]> {
  try {
    // Backend returns { success: true, data: Role[] } or { roles: Role[] }
    // Check GetUserRoles handler - it returns c.JSON(http.StatusOK, gin.H{"roles": roles})
    // So after unwrap, we get { roles: Role[] }
    const response = await apiClient.get<{ roles: Role[] }>(
      `/users/${userId}/roles`,
    );
    return response.data.roles || [];
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to access user roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to view user roles',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('User not found');
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Failed to fetch user roles';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Assigne un rôle à un utilisateur
 * @param userId ID de l'utilisateur
 * @param request Données de la requête (role_id, expires_at optionnel)
 * @throws Error si la requête échoue
 */
export async function assignRole(
  userId: string,
  request: AssignRoleRequest,
): Promise<void> {
  requireFeature('ROLE_MANAGEMENT');
  try {
    await apiClient.post(`/users/${userId}/roles`, request);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage =
          error.response?.data?.error || 'Invalid request data';
        throw new Error(errorMessage);
      }
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to assign roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to assign roles',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('User or role not found');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to assign role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Révoque un rôle d'un utilisateur
 * @param userId ID de l'utilisateur
 * @param roleId ID du rôle à révoquer
 * @throws Error si la requête échoue
 */
export async function revokeRole(
  userId: string,
  roleId: string,
): Promise<void> {
  requireFeature('ROLE_MANAGEMENT');
  try {
    await apiClient.delete(`/users/${userId}/roles/${roleId}`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to revoke roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to revoke roles',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('User role assignment not found');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to revoke role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Crée un nouveau rôle
 * @param role Données du rôle à créer
 * @returns Le rôle créé
 * @throws Error si la requête échoue
 */
export async function createRole(role: Partial<Role>): Promise<Role> {
  try {
    // Backend CreateRole returns c.JSON(http.StatusCreated, gin.H{"role": role})
    // So after unwrap, we get { role: Role }
    const response = await apiClient.post<{ role: Role }>('/roles', role);
    return response.data.role;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Invalid role data';
        throw new Error(errorMessage);
      }
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to create roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to create roles',
        );
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to create role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Met à jour un rôle
 * @param roleId ID du rôle à mettre à jour
 * @param updates Données à mettre à jour
 * @throws Error si la requête échoue
 */
export async function updateRole(
  roleId: string,
  updates: Partial<Role>,
): Promise<void> {
  requireFeature('ROLE_MANAGEMENT');
  try {
    await apiClient.put(`/roles/${roleId}`, updates);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Invalid role data';
        throw new Error(errorMessage);
      }
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to update roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to update roles',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('Role not found or is a system role');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to update role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}

/**
 * Supprime un rôle
 * @param roleId ID du rôle à supprimer
 * @throws Error si la requête échoue
 */
export async function deleteRole(roleId: string): Promise<void> {
  requireFeature('ROLE_MANAGEMENT');
  try {
    await apiClient.delete(`/roles/${roleId}`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage =
          error.response?.data?.error || 'Cannot delete system role';
        throw new Error(errorMessage);
      }
      if (error.response?.status === 401) {
        throw new Error('Unauthorized: Please log in to delete roles');
      }
      if (error.response?.status === 403) {
        throw new Error(
          'Forbidden: You do not have permission to delete roles',
        );
      }
      if (error.response?.status === 404) {
        throw new Error('Role not found');
      }
      const errorMessage =
        error.response?.data?.error || error.message || 'Failed to delete role';
      throw new Error(errorMessage);
    }
    throw error;
  }
}
