import { RouteAccessPolicy } from './RouteAccessPolicy';
import { RouteCatalog } from './RouteCatalog';

describe('RouteAccessPolicy', () => {
  let policy: RouteAccessPolicy;
  let catalog: RouteCatalog;

  beforeEach(() => {
    catalog = new RouteCatalog();
    policy = new RouteAccessPolicy(catalog);
  });

  describe('isPublic', () => {
    it('should return true for public routes', () => {
      const publicRoutes = [
        '/',
        '/leagues',
        '/drivers',
        '/teams',
        '/leaderboards',
        '/races',
        '/sponsor/signup',
        '/auth/login',
        '/auth/signup',
        '/auth/forgot-password',
        '/auth/reset-password',
        '/404',
        '/500',
      ];

      publicRoutes.forEach(route => {
        expect(policy.isPublic(route)).toBe(true);
      });
    });

    it('should return false for protected routes', () => {
      const protectedRoutes = [
        '/dashboard',
        '/onboarding',
        '/profile',
        '/profile/settings',
        '/sponsor/dashboard',
        '/sponsor/billing',
        '/admin/users',
        '/leagues/create',
      ];

      protectedRoutes.forEach(route => {
        expect(policy.isPublic(route)).toBe(false);
      });
    });

    it('should handle wildcard patterns', () => {
      // These should match patterns from RouteCatalog
      expect(policy.isPublic('/leagues/123')).toBe(true);
      expect(policy.isPublic('/drivers/456')).toBe(true);
      expect(policy.isPublic('/teams/789')).toBe(true);
      expect(policy.isPublic('/races/123')).toBe(true);
      expect(policy.isPublic('/races/all')).toBe(true);
    });
  });

  describe('isAuthPage', () => {
    it('should return true for auth pages', () => {
      const authRoutes = [
        '/auth/login',
        '/auth/signup',
        '/auth/forgot-password',
        '/auth/reset-password',
      ];

      authRoutes.forEach(route => {
        expect(policy.isAuthPage(route)).toBe(true);
      });
    });

    it('should return false for non-auth pages', () => {
      const nonAuthRoutes = [
        '/',
        '/dashboard',
        '/leagues',
        '/sponsor/dashboard',
        '/admin/users',
      ];

      nonAuthRoutes.forEach(route => {
        expect(policy.isAuthPage(route)).toBe(false);
      });
    });
  });

  describe('requiredRoles', () => {
    it('should return null for public routes', () => {
      const publicRoutes = [
        '/',
        '/leagues',
        '/drivers',
        '/auth/login',
      ];

      publicRoutes.forEach(route => {
        expect(policy.requiredRoles(route)).toBeNull();
      });
    });

    it('should return null for auth-only routes (no specific role)', () => {
      const authRoutes = [
        '/dashboard',
        '/onboarding',
        '/profile',
        '/profile/settings',
        '/profile/leagues',
      ];

      authRoutes.forEach(route => {
        expect(policy.requiredRoles(route)).toBeNull();
      });
    });

    it('should return sponsor role for sponsor routes', () => {
      const sponsorRoutes = [
        '/sponsor',
        '/sponsor/dashboard',
        '/sponsor/billing',
        '/sponsor/campaigns',
        '/sponsor/leagues',
        '/sponsor/settings',
      ];

      sponsorRoutes.forEach(route => {
        expect(policy.requiredRoles(route)).toEqual(['sponsor']);
      });
    });

    it('should return admin roles for admin routes', () => {
      const adminRoutes = [
        '/admin',
        '/admin/users',
        '/leagues/123/schedule/admin',
        '/leagues/123/roster/admin',
        '/leagues/123/stewarding',
        '/leagues/123/wallet',
      ];

      adminRoutes.forEach(route => {
        expect(policy.requiredRoles(route)).toEqual(['system-owner', 'super-admin', 'league-admin']);
      });
    });

    it('should return steward roles for race stewarding routes', () => {
      const stewardRoutes = [
        '/races/456/stewarding',
      ];

      stewardRoutes.forEach(route => {
        expect(policy.requiredRoles(route)).toEqual(['system-owner', 'super-admin', 'league-steward']);
      });
    });

    it('should handle league-specific admin routes', () => {
      const result = policy.requiredRoles('/leagues/abc-123/settings');
      expect(result).toEqual(['system-owner', 'super-admin', 'league-admin']);
    });

    it('should handle race-specific stewarding routes', () => {
      const result = policy.requiredRoles('/races/xyz-789/stewarding');
      expect(result).toEqual(['system-owner', 'super-admin', 'league-steward']);
    });
  });

  describe('roleHome', () => {
    it('should return correct home path for driver role', () => {
      const result = policy.roleHome('driver');
      expect(result).toBe('/dashboard');
    });

    it('should return correct home path for sponsor role', () => {
      const result = policy.roleHome('sponsor');
      expect(result).toBe('/sponsor/dashboard');
    });

    it('should return correct home path for league-admin role', () => {
      const result = policy.roleHome('league-admin');
      expect(result).toBe('/admin');
    });

    it('should return correct home path for league-steward role', () => {
      const result = policy.roleHome('league-steward');
      expect(result).toBe('/admin');
    });

    it('should return correct home path for league-owner role', () => {
      const result = policy.roleHome('league-owner');
      expect(result).toBe('/admin');
    });

    it('should return correct home path for system-owner role', () => {
      const result = policy.roleHome('system-owner');
      expect(result).toBe('/admin');
    });

    it('should return correct home path for super-admin role', () => {
      const result = policy.roleHome('super-admin');
      expect(result).toBe('/admin');
    });

    it('should handle unknown roles gracefully', () => {
      const result = policy.roleHome('unknown');
      // Should return a sensible default (dashboard)
      expect(result).toBe('/dashboard');
    });
  });

  describe('roleHomeRouteId', () => {
    it('should return correct route ID for driver role', () => {
      const result = policy.roleHomeRouteId('driver');
      expect(result).toBe('protected.dashboard');
    });

    it('should return correct route ID for sponsor role', () => {
      const result = policy.roleHomeRouteId('sponsor');
      expect(result).toBe('sponsor.dashboard');
    });

    it('should return correct route ID for admin roles', () => {
      const adminRoles = ['league-admin', 'league-steward', 'league-owner', 'system-owner', 'super-admin'];
      
      adminRoles.forEach(role => {
        const result = policy.roleHomeRouteId(role);
        expect(result).toBe('admin');
      });
    });
  });

  describe('integration scenarios', () => {
    it('should correctly classify common user journey paths', () => {
      // Public user browsing
      expect(policy.isPublic('/leagues')).toBe(true);
      expect(policy.requiredRoles('/leagues')).toBeNull();

      // Authenticated user
      expect(policy.isPublic('/dashboard')).toBe(false);
      expect(policy.requiredRoles('/dashboard')).toBeNull();

      // Sponsor user
      expect(policy.isPublic('/sponsor/dashboard')).toBe(false);
      expect(policy.requiredRoles('/sponsor/dashboard')).toEqual(['sponsor']);
      expect(policy.roleHome('sponsor')).toBe('/sponsor/dashboard');

      // Admin user
      expect(policy.isPublic('/admin/users')).toBe(false);
      expect(policy.requiredRoles('/admin/users')).toEqual(['system-owner', 'super-admin', 'league-admin']);
      expect(policy.roleHome('league-admin')).toBe('/admin');
    });
  });
});