/**
 * Route Discovery Orchestrator
 *
 * Runs all framework-specific route extractors, deduplicates routes,
 * and builds the unified RouteMap.
 */

import type { ScanFile } from '../../shared/types'
import type { RouteMap, RouteDefinition, MountPoint } from './types'
import { createEmptyRouteMap } from './types'
import { extractExpressRoutes, extractMountPoints } from './express'
import { extractNextJSRoutes } from './nextjs'
import { extractPythonRoutes } from './python'

// Re-export types for convenience
export type { RouteMap, RouteDefinition, RouteInput, MountPoint, RouteFramework } from './types'
export { createEmptyRouteMap } from './types'

/**
 * Discover all routes across all supported frameworks.
 *
 * Runs Express, Next.js, and Python extractors, deduplicates,
 * and builds the fileToRoutes index.
 */
export function discoverRoutes(
  files: ScanFile[],
  frameworkPrimary: string | undefined
): { routeMap: RouteMap; mountPoints: MountPoint[] } {
  const allRoutes: RouteDefinition[] = []
  const allMountPoints: MountPoint[] = []

  for (const file of files) {
    // Express/Fastify/Hono/Koa
    const expressRoutes = extractExpressRoutes(file.content, file.path)
    allRoutes.push(...expressRoutes)

    const mounts = extractMountPoints(file.content, file.path)
    allMountPoints.push(...mounts)

    // Python (Flask/Django)
    const pythonRoutes = extractPythonRoutes(file.content, file.path)
    allRoutes.push(...pythonRoutes)
  }

  // Next.js (needs all files at once for filesystem-based routing)
  const nextjsRoutes = extractNextJSRoutes(files, frameworkPrimary)
  allRoutes.push(...nextjsRoutes)

  // Deduplicate: same file + path + method combo
  const deduped = deduplicateRoutes(allRoutes)

  // Build fileToRoutes index
  const fileToRoutes = new Map<string, RouteDefinition[]>()
  for (const route of deduped) {
    const existing = fileToRoutes.get(route.filePath) || []
    existing.push(route)
    fileToRoutes.set(route.filePath, existing)
  }

  return {
    routeMap: { routes: deduped, fileToRoutes },
    mountPoints: allMountPoints,
  }
}

// ============================================================================
// Internal Helpers
// ============================================================================

function deduplicateRoutes(routes: RouteDefinition[]): RouteDefinition[] {
  const seen = new Set<string>()
  const result: RouteDefinition[] = []

  for (const route of routes) {
    const key = `${route.filePath}:${route.path}:${[...route.methods].sort().join(',')}`
    if (!seen.has(key)) {
      seen.add(key)
      result.push(route)
    }
  }

  return result
}
