import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { of } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
import { AuthActions } from '../store/auth/auth.actions';
import { selectUser, selectAuthState } from '../store/auth/auth.reducer';

export const authGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);
  const store = inject(Store);

  if (!authService.isAuthenticated()) {
    router.navigate(['/login']);
    return false;
  }

  // Ensure user profile is loaded before allowing child routes
  return store.select(selectUser).pipe(
    take(1),
    switchMap(user => {
      if (user) return of(true); // Already loaded

      // Dispatch loadProfile and wait for it to complete
      store.dispatch(AuthActions.loadProfile());
      return store.select(selectAuthState).pipe(
        // Wait until loading is done (success or failure)
        filter(state => !state.loading),
        take(1),
        map(state => {
          if (state.user) return true;

          // Profile load failed — try cached user before giving up
          const cached = authService.getCachedUser();
          if (cached) {
            store.dispatch(AuthActions.loadProfileSuccess({ user: cached }));
            return true;
          }

          // No cached user either — redirect to login
          authService.removeToken();
          router.navigate(['/login']);
          return false;
        })
      );
    })
  );
};

export const guestGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);

  if (!authService.isAuthenticated()) {
    return true;
  }

  router.navigate(['/']);
  return false;
};

/**
 * Route guard that checks permission prefixes from route data.
 * Usage: { path: 'users', canActivate: [permissionGuard], data: { permissions: ['core.users'] } }
 * User needs at least one permission starting with any of the listed prefixes.
 * Super admin (empty roles & permissions) is always allowed.
 */
export const permissionGuard: CanActivateFn = (route) => {
  const store = inject(Store);
  const router = inject(Router);
  const prefixes: string[] = route.data?.['permissions'] || [];

  // No permissions specified = always allowed
  if (prefixes.length === 0) return true;

  // User should already be loaded by authGuard on parent route
  return store.select(selectUser).pipe(
    // Wait for user to be loaded (authGuard ensures this)
    filter(user => user !== null),
    take(1),
    map(user => {
      // Super admin = empty roles & permissions
      if (user!.roles.length === 0 && user!.permissions.length === 0) return true;

      // Check if user has any permission matching any prefix
      const hasPermission = prefixes.some(prefix =>
        user!.permissions.some(p => p.startsWith(prefix))
      );
      if (hasPermission) return true;

      router.navigate(['/dashboard']);
      return false;
    })
  );
};
