import { routes, routeMatchers } from '../routing/RouteConfig';

/**
 * RouteCatalog exposes route IDs and patterns for matching
 * 
 * Route IDs follow the pattern: 'category.routeName'
 * Examples:
 * - 'auth.login' → '/auth/login'
 * - 'protected.dashboard' → '/dashboard'
 * - 'league.detail' → '/leagues/[id]' (pattern)
 */
export class RouteCatalog {
  /**
   * List all public route IDs
   * Public routes are accessible without authentication
   */
  listPublicRoutes(): string[] {
    return [
      'public.home',
      'public.leagues',
      'public.drivers',
      'public.teams',
      'public.leaderboards',
      'public.races',
      'public.sponsorSignup',
      'auth.login',
      'auth.signup',
      'auth.forgotPassword',
      'auth.resetPassword',
      'auth.iRacingStart',
      'auth.iRacingCallback',
      'error.notFound',
      'error.serverError',
      // Parameterized public routes
      'league.detail',
      'league.rulebook',
      'league.schedule',
      'league.standings',
      'driver.detail',
      'team.detail',
      'race.detail',
      'race.results',
      'race.all',
    ];
  }

  /**
   * List all protected route IDs
   * Protected routes require authentication
   */
  listProtectedRoutes(): string[] {
    return [
      'protected.dashboard',
      'protected.onboarding',
      'protected.profile',
      'protected.profileSettings',
      'protected.profileLeagues',
      'protected.profileLiveries',
      'protected.profileLiveryUpload',
      'protected.profileSponsorshipRequests',
      'sponsor.root',
      'sponsor.dashboard',
      'sponsor.billing',
      'sponsor.campaigns',
      'sponsor.leagues',
      'sponsor.settings',
      'admin.root',
      'admin.users',
      'league.create',
      'race.root',
      'team.root',
      'team.leaderboard',
    ];
  }

  /**
   * List all admin route IDs
   * Admin routes require admin-level permissions
   */
  listAdminRoutes(): string[] {
    return [
      'admin.root',
      'admin.users',
      'league.rosterAdmin',
      'league.scheduleAdmin',
      'league.stewarding',
      'league.settings',
      'league.sponsorships',
      'league.wallet',
      'race.stewarding',
    ];
  }

  /**
   * List all sponsor route IDs
   * Sponsor routes require sponsor role
   */
  listSponsorRoutes(): string[] {
    return [
      'sponsor.root',
      'sponsor.dashboard',
      'sponsor.billing',
      'sponsor.campaigns',
      'sponsor.leagues',
      'sponsor.settings',
    ];
  }

  /**
   * Get the path pattern for a route ID
   * @param routeId - Route ID in format 'category.routeName'
   * @returns Path pattern (e.g., '/auth/login' or '/leagues/[id]')
   * @throws Error if route ID is unknown
   */
  getPattern(routeId: string): string {
    const parts = routeId.split('.');
    let route: any = routes;

    for (const part of parts) {
      route = route[part];
      if (!route) {
        throw new Error(`Unknown route ID: ${routeId}`);
      }
    }

    // Handle parameterized routes
    if (typeof route === 'function') {
      // Return pattern with placeholder
      const paramPattern = route('placeholder');
      return paramPattern.replace('/placeholder', '/[id]');
    }

    return route as string;
  }

  /**
   * Check if a path is an auth page
   * @param logicalPath - Path to check
   * @returns True if path is an auth page
   */
  isAuthPage(logicalPath: string): boolean {
    return routeMatchers.isInGroup(logicalPath, 'auth');
  }

  /**
   * Get all route patterns with their IDs
   * @returns Array of route patterns with IDs
   */
  getAllPatterns(): Array<{ routeId: string; pattern: string }> {
    const patterns: Array<{ routeId: string; pattern: string }> = [];

    // Helper to traverse routes and build patterns
    const traverse = (obj: any, prefix: string) => {
      for (const [key, value] of Object.entries(obj)) {
        const routeId = prefix ? `${prefix}.${key}` : key;

        if (typeof value === 'function') {
          // Parameterized route
          const pattern = value('placeholder').replace('/placeholder', '/[id]');
          patterns.push({ routeId, pattern });
        } else if (typeof value === 'object' && value !== null) {
          // Nested category
          traverse(value, routeId);
        } else if (typeof value === 'string') {
          // Simple route
          patterns.push({ routeId, pattern: value });
        }
      }
    };

    traverse(routes, '');
    return patterns;
  }

  /**
   * Get route ID by path
   * @param path - Path to find
   * @returns Route ID or null if not found
   * 
   * Note: This method prioritizes exact matches over parameterized matches.
   * For example, '/leagues/create' will match 'league.create' before 'league.detail'.
   */
  getRouteIdByPath(path: string): string | null {
    const allPatterns = this.getAllPatterns();
    
    // First, try exact matches
    for (const { routeId, pattern } of allPatterns) {
      if (pattern === path) {
        return routeId;
      }
    }
    
    // Then, try parameterized matches
    for (const { routeId, pattern } of allPatterns) {
      if (pattern.includes('[')) {
        const paramPattern = pattern.replace(/\[([^\]]+)\]/g, '([^/]+)');
        const regex = new RegExp(`^${paramPattern}$`);
        if (regex.test(path)) {
          return routeId;
        }
      }
    }

    return null;
  }

  /**
   * Check if a path requires specific role-based access
   * @param logicalPath - Path to check
   * @returns Array of required roles or null
   */
  getRequiredRoles(logicalPath: string): string[] | null {
    // Check admin routes
    if (routeMatchers.isInGroup(logicalPath, 'admin')) {
      return ['system-owner', 'super-admin', 'league-admin'];
    }
    
    // Check sponsor routes
    if (routeMatchers.isInGroup(logicalPath, 'sponsor')) {
      return ['sponsor'];
    }
    
    // Check league admin routes (specific patterns)
    if (logicalPath.match(/\/leagues\/[^/]+\/(roster\/admin|schedule\/admin|stewarding|settings|sponsorships|wallet)/)) {
      return ['system-owner', 'super-admin', 'league-admin'];
    }
    
    // Check race stewarding routes
    if (logicalPath.match(/\/races\/[^/]+\/stewarding/)) {
      return ['system-owner', 'super-admin', 'league-steward'];
    }
    
    // Public or auth-only routes (no specific role)
    return null;
  }

  /**
   * Get the home path for a specific role
   * @param role - The role name
   * @returns The logical path for that role's home page
   */
  getRoleHome(role: string): string {
    const roleHomeMap: Record<string, string> = {
      'driver': '/dashboard',
      'sponsor': '/sponsor/dashboard',
      'league-admin': '/admin',
      'league-steward': '/admin',
      'league-owner': '/admin',
      'system-owner': '/admin',
      'super-admin': '/admin',
    };

    return roleHomeMap[role] || '/dashboard';
  }

  /**
   * Get the route ID for a specific role's home page
   * @param role - The role name
   * @returns The route ID for that role's home page
   */
  getRoleHomeRouteId(role: string): string {
    const roleHomeRouteMap: Record<string, string> = {
      'driver': 'protected.dashboard',
      'sponsor': 'sponsor.dashboard',
      'league-admin': 'admin',
      'league-steward': 'admin',
      'league-owner': 'admin',
      'system-owner': 'admin',
      'super-admin': 'admin',
    };

    return roleHomeRouteMap[role] || 'protected.dashboard';
  }
}