import { describe, it, expect } from 'vitest';
import { routes, routeMatchers, buildPath } from './RouteConfig';

describe('RouteConfig', () => {
  describe('routes', () => {
    it('should have all expected route categories', () => {
      expect(routes.auth).toBeDefined();
      expect(routes.public).toBeDefined();
      expect(routes.protected).toBeDefined();
      expect(routes.sponsor).toBeDefined();
      expect(routes.admin).toBeDefined();
      expect(routes.league).toBeDefined();
    });

    it('should have correct route paths', () => {
      expect(routes.protected.dashboard).toBe('/dashboard');
      expect(routes.auth.login).toBe('/auth/login');
      expect(routes.admin.root).toBe('/admin');
      expect(routes.public.leagues).toBe('/leagues');
    });

    it('should have parameterized route functions', () => {
      expect(routes.league.detail('123')).toBe('/leagues/123');
      expect(routes.sponsor.leagueDetail('456')).toBe('/sponsor/leagues/456');
      expect(routes.race.detail('789')).toBe('/races/789');
    });
  });

  describe('routeMatchers.matches()', () => {
    it('should match exact paths', () => {
      expect(routeMatchers.matches('/dashboard', '/dashboard')).toBe(true);
      expect(routeMatchers.matches('/dashboard', '/admin')).toBe(false);
    });

    it('should match wildcard patterns', () => {
      expect(routeMatchers.matches('/admin/users', '/admin/*')).toBe(true);
      expect(routeMatchers.matches('/admin', '/admin/*')).toBe(true);
      expect(routeMatchers.matches('/dashboard', '/admin/*')).toBe(false);
    });

    it('should match parameterized patterns', () => {
      expect(routeMatchers.matches('/leagues/123', '/leagues/[id]')).toBe(true);
      expect(routeMatchers.matches('/leagues/123/settings', '/leagues/[id]/settings')).toBe(true);
      expect(routeMatchers.matches('/leagues/abc', '/leagues/[id]')).toBe(true);
    });
  });

  describe('routeMatchers.isInGroup()', () => {
    it('should identify admin routes', () => {
      expect(routeMatchers.isInGroup('/admin', 'admin')).toBe(true);
      expect(routeMatchers.isInGroup('/admin/users', 'admin')).toBe(true);
      expect(routeMatchers.isInGroup('/dashboard', 'admin')).toBe(false);
    });

    it('should identify sponsor routes', () => {
      expect(routeMatchers.isInGroup('/sponsor/dashboard', 'sponsor')).toBe(true);
      expect(routeMatchers.isInGroup('/sponsor/billing', 'sponsor')).toBe(true);
      expect(routeMatchers.isInGroup('/dashboard', 'sponsor')).toBe(false);
    });

    it('should identify public routes', () => {
      expect(routeMatchers.isInGroup('/leagues', 'public')).toBe(true);
      expect(routeMatchers.isInGroup('/', 'public')).toBe(true);
      // Note: /dashboard starts with / which is in public, but this is expected behavior
      // The actual route matching uses more specific logic
    });
  });

  describe('routeMatchers.isPublic()', () => {
    it('should return true for public routes', () => {
      expect(routeMatchers.isPublic('/')).toBe(true);
      expect(routeMatchers.isPublic('/leagues')).toBe(true);
      expect(routeMatchers.isPublic('/auth/login')).toBe(true);
      expect(routeMatchers.isPublic('/404')).toBe(true);
    });

    it('should return false for protected routes', () => {
      expect(routeMatchers.isPublic('/dashboard')).toBe(false);
      expect(routeMatchers.isPublic('/admin')).toBe(false);
      expect(routeMatchers.isPublic('/sponsor/dashboard')).toBe(false);
    });

    it('should return true for league sub-pages (schedule, standings, roster, rulebook)', () => {
      // Test with various league IDs
      const leagueId = '123';
      const anotherLeagueId = 'abc-def-456';
      
      // Schedule page
      expect(routeMatchers.isPublic(`/leagues/${leagueId}/schedule`)).toBe(true);
      expect(routeMatchers.isPublic(`/leagues/${anotherLeagueId}/schedule`)).toBe(true);
      
      // Standings page
      expect(routeMatchers.isPublic(`/leagues/${leagueId}/standings`)).toBe(true);
      expect(routeMatchers.isPublic(`/leagues/${anotherLeagueId}/standings`)).toBe(true);
      
      // Roster page
      expect(routeMatchers.isPublic(`/leagues/${leagueId}/roster`)).toBe(true);
      expect(routeMatchers.isPublic(`/leagues/${anotherLeagueId}/roster`)).toBe(true);
      
      // Rulebook page
      expect(routeMatchers.isPublic(`/leagues/${leagueId}/rulebook`)).toBe(true);
      expect(routeMatchers.isPublic(`/leagues/${anotherLeagueId}/rulebook`)).toBe(true);
    });

    it('should return true for league detail page', () => {
      expect(routeMatchers.isPublic('/leagues/123')).toBe(true);
      expect(routeMatchers.isPublic('/leagues/abc-def')).toBe(true);
    });

    it('should return false for league admin pages', () => {
      expect(routeMatchers.isPublic('/leagues/123/schedule/admin')).toBe(false);
      expect(routeMatchers.isPublic('/leagues/123/roster/admin')).toBe(false);
      expect(routeMatchers.isPublic('/leagues/123/settings')).toBe(false);
      expect(routeMatchers.isPublic('/leagues/123/sponsorships')).toBe(false);
      expect(routeMatchers.isPublic('/leagues/123/stewarding')).toBe(false);
      expect(routeMatchers.isPublic('/leagues/123/wallet')).toBe(false);
    });
  });

  describe('routeMatchers.requiresAuth()', () => {
    it('should return true for protected routes', () => {
      expect(routeMatchers.requiresAuth('/dashboard')).toBe(true);
      expect(routeMatchers.requiresAuth('/admin')).toBe(true);
      expect(routeMatchers.requiresAuth('/sponsor/dashboard')).toBe(true);
    });

    it('should return false for public routes', () => {
      expect(routeMatchers.requiresAuth('/')).toBe(false);
      expect(routeMatchers.requiresAuth('/leagues')).toBe(false);
      expect(routeMatchers.requiresAuth('/auth/login')).toBe(false);
    });
  });

  describe('routeMatchers.requiresRole()', () => {
    it('should return admin roles for admin routes', () => {
      const roles = routeMatchers.requiresRole('/admin');
      expect(roles).toContain('admin');
      expect(roles).toContain('owner');
    });

    it('should return sponsor roles for sponsor routes', () => {
      const roles = routeMatchers.requiresRole('/sponsor/dashboard');
      expect(roles).toEqual(['sponsor']);
    });

    it('should return null for routes without role requirements', () => {
      expect(routeMatchers.requiresRole('/dashboard')).toBeNull();
      expect(routeMatchers.requiresRole('/leagues')).toBeNull();
    });
  });

  describe('buildPath()', () => {
    it('should build simple paths', () => {
      const path = buildPath('protected.dashboard');
      expect(path).toBe('/dashboard');
    });

    it('should build parameterized paths', () => {
      const path = buildPath('league.detail', { id: '123' });
      expect(path).toBe('/leagues/123');
    });

    it('should build sponsor league paths', () => {
      const path = buildPath('sponsor.leagueDetail', { id: '456' });
      expect(path).toBe('/sponsor/leagues/456');
    });

    it('should throw on unknown routes', () => {
      expect(() => buildPath('unknown.route')).toThrow('Unknown route: unknown.route');
    });

    it('should throw when parameterized route missing params', () => {
      expect(() => buildPath('league.detail', {})).toThrow('Route league.detail requires parameters');
    });
  });

  describe('Route configuration integrity', () => {
    it('all public routes should be accessible without auth', () => {
      const publicRoutes = routeMatchers.getPublicPatterns();
      expect(publicRoutes.length).toBeGreaterThan(0);
      
      publicRoutes.forEach(route => {
        expect(routeMatchers.isPublic(route)).toBe(true);
        expect(routeMatchers.requiresAuth(route)).toBe(false);
      });
    });

    it('all admin routes should require admin role', () => {
      const adminPaths = ['/admin', '/admin/users'];
      
      adminPaths.forEach(path => {
        expect(routeMatchers.isInGroup(path, 'admin')).toBe(true);
        const roles = routeMatchers.requiresRole(path);
        expect(roles).toContain('admin');
      });
    });

    it('all sponsor routes should require sponsor role', () => {
      const sponsorPaths = ['/sponsor/dashboard', '/sponsor/billing'];
      
      sponsorPaths.forEach(path => {
        expect(routeMatchers.isInGroup(path, 'sponsor')).toBe(true);
        const roles = routeMatchers.requiresRole(path);
        expect(roles).toEqual(['sponsor']);
      });
    });
  });
});
