// src/app/core/services/role-management.service.ts
import { Injectable, inject } from '@angular/core';
import { HubUsersService, UserRole } from '../../modules/users/services/users.service';
import { BehaviorSubject, Observable, map, tap, of, catchError } from 'rxjs';

export interface RolePermission {
  canCreateUsers: boolean;
  canEditUsers: boolean;
  canDeleteUsers: boolean;
  canManageRoles: boolean;
  canViewStats: boolean;
  canManageMerchants: boolean;
  canAccessAdmin: boolean;
  canAccessSupport: boolean;
  canAccessPartner: boolean;
}

// Interface simplifiée pour la réponse API
export interface AvailableRoleResponse {
  value: UserRole;
  label: string;
  description: string;
}

export interface AvailableRolesResponse {
  roles: AvailableRoleResponse[];
}

// Interface étendue pour l'usage interne avec les permissions
export interface AvailableRole extends AvailableRoleResponse {
  permissions: RolePermission;
}

export interface AvailableRolesWithPermissions {
  roles: AvailableRole[];
}

@Injectable({
  providedIn: 'root'
})
export class RoleManagementService {
  private hubUsersService = inject(HubUsersService);
  
  private availableRoles$ = new BehaviorSubject<AvailableRolesWithPermissions | null>(null);
  private currentUserRole$ = new BehaviorSubject<UserRole | null>(null);

  /**
   * Charge les rôles disponibles depuis l'API et les enrichit avec les permissions
   */
  loadAvailableRoles(): Observable<AvailableRolesWithPermissions> {
    return this.hubUsersService.getAvailableHubRoles().pipe(
      map(apiResponse => {
        // Enrichir les rôles de l'API avec les permissions
        const rolesWithPermissions: AvailableRole[] = apiResponse.roles.map(role => ({
          ...role,
          permissions: this.getPermissionsForRole(role.value)
        }));

        const result: AvailableRolesWithPermissions = {
          roles: rolesWithPermissions
        };

        this.availableRoles$.next(result);
        return result;
      }),
      catchError(error => {
        console.error('Error loading available roles:', error);
        // Fallback avec les rôles par défaut
        const defaultRoles: AvailableRolesWithPermissions = {
          roles: [
            {
              value: UserRole.DCB_ADMIN,
              label: 'DCB Admin',
              description: 'Full administrative access to the entire system',
              permissions: this.getPermissionsForRole(UserRole.DCB_ADMIN)
            },
            {
              value: UserRole.DCB_SUPPORT,
              label: 'DCB Support',
              description: 'Support access with limited administrative capabilities',
              permissions: this.getPermissionsForRole(UserRole.DCB_SUPPORT)
            },
            {
              value: UserRole.DCB_PARTNER,
              label: 'DCB Partner',
              description: 'Merchant partner with access to their own merchant ecosystem',
              permissions: this.getPermissionsForRole(UserRole.DCB_PARTNER)
            }
          ]
        };
        
        this.availableRoles$.next(defaultRoles);
        return of(defaultRoles);
      })
    );
  }

  /**
   * Récupère les rôles disponibles depuis le cache ou l'API
   */
  getAvailableRoles(): Observable<AvailableRolesWithPermissions> {
    const cached = this.availableRoles$.value;
    if (cached) {
      return of(cached);
    }
    return this.loadAvailableRoles();
  }

  /**
   * Récupère les rôles disponibles sous forme simplifiée (pour les selects)
   */
  getAvailableRolesSimple(): Observable<AvailableRoleResponse[]> {
    return this.getAvailableRoles().pipe(
      map(response => response.roles.map(role => ({
        value: role.value,
        label: role.label,
        description: role.description
      })))
    );
  }

  // ... (le reste des méthodes reste identique)

  /**
   * Définit le rôle de l'utilisateur courant
   */
  setCurrentUserRole(role: UserRole): void {
    this.currentUserRole$.next(role);
  }

  /**
   * Récupère le rôle de l'utilisateur courant
   */
  getCurrentUserRole(): Observable<UserRole | null> {
    return this.currentUserRole$.asObservable();
  }

  /**
   * Récupère les permissions détaillées selon le rôle
   */
  getPermissionsForRole(role: UserRole): RolePermission {
    switch (role) {
      case UserRole.DCB_ADMIN:
        return {
          canCreateUsers: true,
          canEditUsers: true,
          canDeleteUsers: true,
          canManageRoles: true,
          canViewStats: true,
          canManageMerchants: true,
          canAccessAdmin: true,
          canAccessSupport: true,
          canAccessPartner: true
        };
      
      case UserRole.DCB_SUPPORT:
        return {
          canCreateUsers: true,
          canEditUsers: true,
          canDeleteUsers: false,
          canManageRoles: false,
          canViewStats: true,
          canManageMerchants: true,
          canAccessAdmin: false,
          canAccessSupport: true,
          canAccessPartner: true
        };
      
      case UserRole.DCB_PARTNER:
        return {
          canCreateUsers: false,
          canEditUsers: false,
          canDeleteUsers: false,
          canManageRoles: false,
          canViewStats: false,
          canManageMerchants: false,
          canAccessAdmin: false,
          canAccessSupport: false,
          canAccessPartner: true
        };
      
      default:
        return {
          canCreateUsers: false,
          canEditUsers: false,
          canDeleteUsers: false,
          canManageRoles: false,
          canViewStats: false,
          canManageMerchants: false,
          canAccessAdmin: false,
          canAccessSupport: false,
          canAccessPartner: false
        };
    }
  }

  /**
   * Vérifie si un rôle peut être attribué par l'utilisateur courant
   */
  canAssignRole(currentUserRole: UserRole | null, targetRole: UserRole): boolean {
    if (!currentUserRole) return false;

    // Seuls les admins peuvent attribuer tous les rôles
    if (currentUserRole === UserRole.DCB_ADMIN) {
      return true;
    }
    
    // Les supports ne peuvent créer que d'autres supports
    if (currentUserRole === UserRole.DCB_SUPPORT) {
      return targetRole === UserRole.DCB_SUPPORT;
    }
    
    return false;
  }

  /**
   * Vérifie si l'utilisateur courant peut créer des utilisateurs
   */
  canCreateUsers(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canCreateUsers : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut éditer des utilisateurs
   */
  canEditUsers(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canEditUsers : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut supprimer des utilisateurs
   */
  canDeleteUsers(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canDeleteUsers : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut gérer les rôles
   */
  canManageRoles(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canManageRoles : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut accéder aux statistiques
   */
  canViewStats(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canViewStats : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut gérer les merchants
   */
  canManageMerchants(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canManageMerchants : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut accéder à l'admin
   */
  canAccessAdmin(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canAccessAdmin : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut accéder au support
   */
  canAccessSupport(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canAccessSupport : false;
  }

  /**
   * Vérifie si l'utilisateur courant peut accéder à l'espace partenaire
   */
  canAccessPartner(currentUserRole: UserRole | null): boolean {
    return currentUserRole ? this.getPermissionsForRole(currentUserRole).canAccessPartner : false;
  }

  /**
   * Récupère le libellé d'un rôle
   */
  getRoleLabel(role: UserRole): string {
    switch (role) {
      case UserRole.DCB_ADMIN:
        return 'Administrateur DCB';
      case UserRole.DCB_SUPPORT:
        return 'Support DCB';
      case UserRole.DCB_PARTNER:
        return 'Partenaire DCB';
      default:
        return 'Rôle inconnu';
    }
  }

  /**
   * Récupère la classe CSS pour un badge de rôle
   */
  getRoleBadgeClass(role: UserRole): string {
    switch (role) {
      case UserRole.DCB_ADMIN:
        return 'bg-danger';
      case UserRole.DCB_SUPPORT:
        return 'bg-info';
      case UserRole.DCB_PARTNER:
        return 'bg-success';
      default:
        return 'bg-secondary';
    }
  }

  /**
   * Récupère l'icône pour un rôle
   */
  getRoleIcon(role: UserRole): string {
    switch (role) {
      case UserRole.DCB_ADMIN:
        return 'lucideShield';
      case UserRole.DCB_SUPPORT:
        return 'lucideHeadphones';
      case UserRole.DCB_PARTNER:
        return 'lucideBuilding';
      default:
        return 'lucideUser';
    }
  }

  /**
   * Vérifie si un rôle est un rôle administrateur
   */
  isAdminRole(role: UserRole): boolean {
    return role === UserRole.DCB_ADMIN;
  }

  /**
   * Vérifie si un rôle est un rôle support
   */
  isSupportRole(role: UserRole): boolean {
    return role === UserRole.DCB_SUPPORT;
  }

  /**
   * Vérifie si un rôle est un rôle partenaire
   */
  isPartnerRole(role: UserRole): boolean {
    return role === UserRole.DCB_PARTNER;
  }

  /**
   * Récupère tous les rôles disponibles sous forme de tableau
   */
  getAllRoles(): UserRole[] {
    return [UserRole.DCB_ADMIN, UserRole.DCB_SUPPORT, UserRole.DCB_PARTNER];
  }

  /**
   * Récupère les rôles que l'utilisateur courant peut attribuer
   */
  getAssignableRoles(currentUserRole: UserRole | null): UserRole[] {
    if (!currentUserRole) return [];

    if (currentUserRole === UserRole.DCB_ADMIN) {
      return this.getAllRoles();
    }

    if (currentUserRole === UserRole.DCB_SUPPORT) {
      return [UserRole.DCB_SUPPORT];
    }

    return [];
  }

  /**
   * Réinitialise le cache des rôles
   */
  clearCache(): void {
    this.availableRoles$.next(null);
  }
}