import { routes, routeMatchers } from '../../../apps/website/lib/routing/RouteConfig';
import { seedId } from '../../../adapters/bootstrap/racing/SeedIdHelper';

export type RouteAccess = 'public' | 'auth' | 'admin' | 'sponsor';
export type RouteParams = Record<string, string>;

export interface WebsiteRouteDefinition {
  pathTemplate: string;
  params?: RouteParams;
  access: RouteAccess;
  expectedPathTemplate?: string;
  allowNotFound?: boolean;
}

export class WebsiteRouteManager {
  // Generate IDs the same way the seed does
  private static getPersistenceMode(): 'postgres' | 'inmemory' {
    const mode = (process.env.GRIDPILOT_API_PERSISTENCE as 'postgres' | 'inmemory') || 'postgres';
    console.log(`[WebsiteRouteManager] Persistence mode: ${mode}`);
    return mode;
  }

  public static readonly IDs = {
    get LEAGUE() { return seedId('league-1', WebsiteRouteManager.getPersistenceMode()); },
    get DRIVER() { return seedId('driver-1', WebsiteRouteManager.getPersistenceMode()); },
    get TEAM() { return seedId('team-1', WebsiteRouteManager.getPersistenceMode()); },
    get RACE() { return seedId('race-1', WebsiteRouteManager.getPersistenceMode()); },
    get PROTEST() { return seedId('protest-1', WebsiteRouteManager.getPersistenceMode()); },
  };

  public resolvePathTemplate(pathTemplate: string, params: RouteParams = {}): string {
    return pathTemplate.replace(/\[([^\]]+)\]/g, (_match, key) => {
      const replacement = params[key];
      if (!replacement) {
        throw new Error(`Missing route param "${key}" for template "${pathTemplate}"`);
      }
      return replacement;
    });
  }

  public getWebsiteRouteInventory(): WebsiteRouteDefinition[] {
    const result: WebsiteRouteDefinition[] = [];

    const pushRoute = (pathTemplate: string, params?: RouteParams) => {
      result.push({
        pathTemplate,
        ...(params ? { params } : {}),
        access: this.getAccessLevel(pathTemplate),
      });
    };

    const processGroup = (group: keyof typeof routes, groupRoutes: Record<string, string | ((id: string) => string)>) => {
      Object.values(groupRoutes).forEach((value) => {
        if (typeof value === 'function') {
          let id = WebsiteRouteManager.IDs.LEAGUE;
          if (group === 'driver') id = WebsiteRouteManager.IDs.DRIVER;
          if (group === 'team') id = WebsiteRouteManager.IDs.TEAM;
          if (group === 'race') id = WebsiteRouteManager.IDs.RACE;
          
          const template = value(id);
          pushRoute(template, { id });
          return;
        }

        pushRoute(value);
      });
    };

    processGroup('auth', routes.auth);
    processGroup('public', routes.public);
    processGroup('protected', routes.protected);
    processGroup('sponsor', routes.sponsor);
    processGroup('admin', routes.admin);
    processGroup('league', routes.league);
    processGroup('race', routes.race);
    processGroup('team', routes.team);
    processGroup('driver', routes.driver);
    processGroup('error', routes.error);

    return result.sort((a, b) => a.pathTemplate.localeCompare(b.pathTemplate));
  }

  public getParamEdgeCases(): WebsiteRouteDefinition[] {
    // Use non-existent UUIDs that will trigger 404 responses
    const nonExistentId = '00000000-0000-0000-0000-000000000000';
    return [
      { pathTemplate: '/races/[id]', params: { id: nonExistentId }, access: 'public', allowNotFound: true },
      { pathTemplate: '/leagues/[id]', params: { id: nonExistentId }, access: 'public', allowNotFound: true },
    ];
  }

  public getFaultInjectionRoutes(): WebsiteRouteDefinition[] {
    return [
      { pathTemplate: '/leagues/[id]', params: { id: WebsiteRouteManager.IDs.LEAGUE }, access: 'public' },
      { pathTemplate: '/leagues/[id]/schedule/admin', params: { id: WebsiteRouteManager.IDs.LEAGUE }, access: 'admin' },
      { pathTemplate: '/sponsor/dashboard', access: 'sponsor' },
      { pathTemplate: '/races/[id]', params: { id: WebsiteRouteManager.IDs.RACE }, access: 'public' },
    ];
  }

  public getAuthDriftRoutes(): WebsiteRouteDefinition[] {
    return [{ pathTemplate: '/sponsor/dashboard', access: 'sponsor' }];
  }

  public getAccessLevel(pathTemplate: string): RouteAccess {
    // NOTE: `routeMatchers.isInGroup(path, 'public')` is prefix-based and will treat everything
    // as public because the home route is `/`. Use `isPublic()` for correct classification.
    
    // Check public first to ensure public routes nested under protected prefixes (e.g. /sponsor/signup)
    // are correctly classified as public.
    if (routeMatchers.isPublic(pathTemplate)) return 'public';
    
    if (routeMatchers.isInGroup(pathTemplate, 'admin')) return 'admin';
    if (routeMatchers.isInGroup(pathTemplate, 'sponsor')) return 'sponsor';
    if (routeMatchers.requiresAuth(pathTemplate)) return 'auth';
    return 'public';
  }
}