import { buildFindingRouteAnnotation, buildFileRouteSummary } from '../../validate/request-builder'
import type { RouteMap, RouteDefinition } from '../../model/route-discovery'
import type { Vulnerability } from '../../shared/types'

function makeRoute(overrides: Partial<RouteDefinition> = {}): RouteDefinition {
  return {
    filePath: 'src/api/users.ts',
    methods: ['GET'],
    path: '/api/users',
    handler: 'getUsers',
    handlerLine: 5,
    framework: 'express',
    authMiddleware: [],
    rateLimiting: false,
    isPublic: false,
    inputs: [],
    ...overrides,
  }
}

function makeFinding(overrides: Partial<Vulnerability> = {}): Vulnerability {
  return {
    id: 'test-1',
    filePath: 'src/api/users.ts',
    lineNumber: 10,
    lineContent: 'const data = req.body',
    severity: 'medium',
    category: 'missing_auth',
    title: 'Missing auth',
    description: 'No auth check',
    confidence: 'medium',
    layer: 2,
    ...overrides,
  }
}

function makeRouteMap(routes: RouteDefinition[]): RouteMap {
  const fileToRoutes = new Map<string, RouteDefinition[]>()
  for (const r of routes) {
    const existing = fileToRoutes.get(r.filePath) || []
    existing.push(r)
    fileToRoutes.set(r.filePath, existing)
  }
  return { routes, fileToRoutes }
}

describe('Route Annotations', () => {
  describe('buildFindingRouteAnnotation', () => {
    it('returns route context for matching file', () => {
      const route = makeRoute({ authMiddleware: ['authGuard'] })
      const routeMap = makeRouteMap([route])
      const finding = makeFinding()
      const annotation = buildFindingRouteAnnotation(finding, 'src/api/users.ts', routeMap)

      expect(annotation).toContain('Route Context')
      expect(annotation).toContain('express')
      expect(annotation).toContain('/api/users')
      expect(annotation).toContain('authGuard')
    })

    it('shows NONE for missing auth', () => {
      const route = makeRoute()
      const routeMap = makeRouteMap([route])
      const finding = makeFinding()
      const annotation = buildFindingRouteAnnotation(finding, 'src/api/users.ts', routeMap)

      expect(annotation).toContain('Auth middleware: NONE')
    })

    it('returns empty for non-route files', () => {
      const routeMap = makeRouteMap([])
      const finding = makeFinding({ filePath: 'src/utils.ts' })
      const annotation = buildFindingRouteAnnotation(finding, 'src/utils.ts', routeMap)

      expect(annotation).toBe('')
    })

    it('selects closest route to finding line', () => {
      const route1 = makeRoute({ handlerLine: 5, path: '/api/users' })
      const route2 = makeRoute({ handlerLine: 20, path: '/api/items' })
      const routeMap = makeRouteMap([route1, route2])
      const finding = makeFinding({ lineNumber: 25 })
      const annotation = buildFindingRouteAnnotation(finding, 'src/api/users.ts', routeMap)

      expect(annotation).toContain('/api/items')
    })

    it('shows rate limiting status', () => {
      const route = makeRoute({ rateLimiting: true })
      const routeMap = makeRouteMap([route])
      const finding = makeFinding()
      const annotation = buildFindingRouteAnnotation(finding, 'src/api/users.ts', routeMap)

      expect(annotation).toContain('Rate limiting: Yes')
    })

    it('shows public endpoint flag', () => {
      const route = makeRoute({ isPublic: true })
      const routeMap = makeRouteMap([route])
      const finding = makeFinding()
      const annotation = buildFindingRouteAnnotation(finding, 'src/api/users.ts', routeMap)

      expect(annotation).toContain('Public endpoint: Yes')
    })
  })

  describe('buildFileRouteSummary', () => {
    it('returns route map summary', () => {
      const routes = [
        makeRoute({ methods: ['GET'], path: '/api/users', handlerLine: 5, authMiddleware: ['auth'] }),
        makeRoute({ methods: ['POST'], path: '/api/users', handlerLine: 15 }),
      ]
      const routeMap = makeRouteMap(routes)
      const summary = buildFileRouteSummary('src/api/users.ts', routeMap)

      expect(summary).toContain('Route Map')
      expect(summary).toContain('GET')
      expect(summary).toContain('POST')
      expect(summary).toContain('[auth: auth]')
      expect(summary).toContain('[no auth]')
    })

    it('returns empty for non-route files', () => {
      const routeMap = makeRouteMap([])
      const summary = buildFileRouteSummary('src/utils.ts', routeMap)
      expect(summary).toBe('')
    })

    it('shows rate limiting and public flags', () => {
      const route = makeRoute({ rateLimiting: true, isPublic: true })
      const routeMap = makeRouteMap([route])
      const summary = buildFileRouteSummary('src/api/users.ts', routeMap)

      expect(summary).toContain('[rate-limited]')
      expect(summary).toContain('[public]')
    })
  })
})
