// src/app/core/guards/auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { RoleService } from '../services/role.service';
import { map, catchError, of, tap, switchMap } from 'rxjs';

export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
  const authService = inject(AuthService);
  const roleService = inject(RoleService);
  const router = inject(Router);

  // Attendre que l'initialisation du service Auth soit terminée
  return authService.getInitializedState().pipe(
    switchMap(initialized => {
      if (!initialized) {
        return of(false);
      }

      // 🔒 Étape 1 : Vérifier si déjà authentifié
      if (authService.isAuthenticated()) {
        return of(checkRoleAccess(route, roleService, router, state.url));
      }

      // 🔄 Étape 2 : Tenter un rafraîchissement du token s’il existe
      const refreshToken = authService.getRefreshToken();
      if (refreshToken) {
        return authService.refreshAccessToken().pipe(
          tap(() => {
            // Recharger les rôles après un refresh réussi
            roleService.refreshRoles();
          }),
          map(() => checkRoleAccess(route, roleService, router, state.url)),
          catchError(() => {
            // En cas d’échec de refresh → déconnexion + redirection login
            authService.logout().subscribe();
            return of(redirectToLogin(router, state.url));
          })
        );
      }

      // 🚫 Étape 3 : Aucun token → redirection vers login
      return of(redirectToLogin(router, state.url));
    }),
    catchError(() => {
      return of(redirectToLogin(router, state.url));
    })
  );
};

/**
 * Vérifie l'accès basé sur les rôles requis
 */
function checkRoleAccess(
  route: ActivatedRouteSnapshot, 
  roleService: RoleService, 
  router: Router, 
  currentUrl: string
): boolean {
  const requiredRoles = route.data?.['roles'] as string[];

  // Si aucun rôle requis → accès autorisé
  if (!requiredRoles || requiredRoles.length === 0) {
    return true;
  }

  const hasRequiredRole = roleService.hasAnyRole(requiredRoles);
  const currentUserRoles = roleService.getCurrentUserRoles();

  // ✅ L’utilisateur possède un des rôles requis
  if (hasRequiredRole) {
    return true;
  }

  // ❌ Sinon → rediriger vers une page "non autorisée"
  router.navigate(['/unauthorized'], {
    queryParams: {
      requiredRoles: requiredRoles.join(','),
      currentRoles: currentUserRoles.join(','),
      attemptedUrl: currentUrl
    },
    replaceUrl: true
  });
  
  return false;
}

/**
 * Redirige vers la page de login avec un returnUrl
 */
function redirectToLogin(router: Router, returnUrl: string): boolean {
  router.navigate(['/auth/login'], { 
    queryParams: { returnUrl },
    replaceUrl: true
  });
  
  return false;
}
