import { Injectable } from '@angular/core'; import { Observable, of, BehaviorSubject } from 'rxjs'; import { map, catchError, switchMap, take, filter, tap } from 'rxjs/operators'; import { UserRole, RoleManagementService } from '@core/services/hub-users-roles-management.service'; import { MerchantConfigService } from '@modules/merchant-config/merchant-config.service'; import { AuthService } from '@core/services/auth.service'; export interface DashboardAccess { isHubUser: boolean; isMerchantUser: boolean; userRole: UserRole; merchantId?: number; } export interface AllowedMerchant { id: number | undefined; name: string; } @Injectable({ providedIn: 'root' }) export class DashboardAccessService { private accessCache: DashboardAccess | null = null; private merchantsCache: AllowedMerchant[] | null = null; private currentMerchantId: number | null = null; private ready$ = new BehaviorSubject(false); private profileLoaded = false; constructor( private roleService: RoleManagementService, private merchantService: MerchantConfigService, private authService: AuthService ) { // Initialisation simple this.initialize(); } private initialize(): void { console.log('🚀 DashboardAccessService: Initialisation'); // S'abonner aux changements de profil this.authService.getUserProfile().subscribe({ next: (profile) => { if (profile) { console.log('✅ DashboardAccessService: Profil chargĂ©', { username: profile.username, merchantPartnerId: profile.merchantPartnerId, userType: profile.userType }); this.profileLoaded = true; this.ready$.next(true); } }, error: (err) => { console.error('❌ DashboardAccessService: Erreur de profil:', err); this.profileLoaded = false; this.ready$.next(false); } }); // Nettoyer Ă  la dĂ©connexion this.authService.getAuthState().subscribe(isAuthenticated => { if (!isAuthenticated) { console.log('🚹 DashboardAccessService: DĂ©connexion dĂ©tectĂ©e'); this.clearCache(); this.profileLoaded = false; this.ready$.next(false); } }); } // Attendre que le service soit prĂȘt AVEC PROFIL CHARGÉ waitForReady(): Observable { return this.ready$.pipe( filter(ready => ready && this.profileLoaded), take(1), tap(() => { console.log('✅ DashboardAccessService: waitForReady() - Service vraiment prĂȘt'); }) ); } // Obtenir l'accĂšs dashboard getDashboardAccess(): DashboardAccess { if (this.accessCache) { return this.accessCache; } // VÉRIFIER que le profil est chargĂ© if (!this.profileLoaded) { console.warn('⚠ DashboardAccessService: Tentative d\'accĂšs avant chargement du profil'); throw new Error('Profil non chargĂ©'); } const profile = this.authService.getCurrentUserProfile(); // VÉRIFIER que le profil existe if (!profile) { console.error('❌ DashboardAccessService: Profil null dans getDashboardAccess()'); throw new Error('Profil utilisateur non disponible'); } console.log('📊 DashboardAccessService: getDashboardAccess() avec profil:', { username: profile.username, merchantPartnerId: profile.merchantPartnerId, userType: profile.userType }); const userRole = this.roleService.getCurrentRole(); const isHubUser = this.roleService.isHubUser(); let merchantId: number | undefined = undefined; if (!isHubUser && profile.merchantPartnerId) { merchantId = Number(profile.merchantPartnerId); if (isNaN(merchantId) || merchantId <= 0) { console.warn(`⚠ DashboardAccessService: merchantPartnerId invalide: ${profile.merchantPartnerId}`); merchantId = undefined; } } this.accessCache = { isHubUser, isMerchantUser: !isHubUser, userRole: userRole || UserRole.DCB_SUPPORT, merchantId }; console.log('🎯 DashboardAccessService: AccĂšs créé:', this.accessCache); return this.accessCache; } // Obtenir l'accĂšs dashboard avec attente getDashboardAccessAsync(): Observable { return this.waitForReady().pipe( map(() => this.getDashboardAccess()) ); } // Obtenir les marchands disponibles getAvailableMerchants(): Observable { return this.waitForReady().pipe( switchMap(() => { if (this.merchantsCache) { return of(this.merchantsCache); } const access = this.getDashboardAccess(); if (access.isHubUser) { return this.merchantService.getAllMerchants().pipe( map(merchants => { const available: AllowedMerchant[] = merchants.items.map(m => ({ id: m.id, name: m.name })); // Option globale pour les hub users available.unshift({ id: 0, name: '🌐 DonnĂ©es globales' }); this.merchantsCache = available; return available; }), catchError(() => { return of([{ id: 0, name: '🌐 DonnĂ©es globales' }]); }) ); } else { // Merchant user: seulement son merchant const merchantId = access.merchantId; if (merchantId) { const merchants = [{ id: merchantId, name: `đŸȘ Merchant ${merchantId}` }]; this.merchantsCache = merchants; return of(merchants); } return of([]); } }) ); } // DĂ©finir le marchand sĂ©lectionnĂ© (hub users seulement) setSelectedMerchantId(merchantId: number): void { if (this.getDashboardAccess().isHubUser) { this.currentMerchantId = merchantId; } } // Obtenir le marchand sĂ©lectionnĂ© getSelectedMerchantId(): number | null { const access = this.getDashboardAccess(); if (access.isMerchantUser) { return access.merchantId || null; } return this.currentMerchantId; } // Nettoyer le cache clearCache(): void { this.accessCache = null; this.merchantsCache = null; this.currentMerchantId = null; } // ============ MÉTHODES UTILITAIRES SIMPLES ============ shouldShowSystemHealth(): boolean { return this.getDashboardAccess().isHubUser; } shouldShowAlerts(): boolean { return true; } canTriggerSync(): boolean { const access = this.getDashboardAccess(); return access.isHubUser && access.userRole === UserRole.DCB_ADMIN; } canManageMerchants(): boolean { const access = this.getDashboardAccess(); return access.isHubUser && access.userRole === UserRole.DCB_ADMIN; } canSelectMerchant(): boolean { return this.getDashboardAccess().isHubUser; } canEditMerchantFilter(): boolean { const access = this.getDashboardAccess(); if (access.isHubUser) { return access.userRole === UserRole.DCB_ADMIN; } return access.userRole === UserRole.DCB_PARTNER_ADMIN; } shouldShowMerchantId(): boolean { const access = this.getDashboardAccess(); return access.isMerchantUser || (access.isHubUser && this.getSelectedMerchantId() !== null); } canViewGlobalData(): boolean { return this.getDashboardAccess().isHubUser; } isViewingGlobalData(): boolean { const access = this.getDashboardAccess(); if (access.isHubUser) { return this.currentMerchantId === 0 || this.currentMerchantId === null; } return false; } getCurrentMerchantName(): string { const access = this.getDashboardAccess(); if (access.isMerchantUser && access.merchantId) { return `Merchant ${access.merchantId}`; } if (access.isHubUser) { if (this.currentMerchantId === 0 || this.currentMerchantId === null) { return 'DonnĂ©es globales'; } else if (this.currentMerchantId) { return `Merchant ${this.currentMerchantId}`; } } return 'Inconnu'; } }