import { extractNextJSRoutes } from '../../../model/route-discovery/nextjs'
import type { ScanFile } from '../../../shared/types'

function makeFile(path: string, content: string): ScanFile {
  return { path, content, language: 'typescript' }
}

describe('Next.js Route Extractor', () => {
  it('extracts App Router GET export', () => {
    const files = [
      makeFile('src/app/api/users/route.ts', `
export async function GET(request: Request) {
  return Response.json({ users: [] })
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    expect(routes[0].methods).toEqual(['GET'])
    expect(routes[0].path).toBe('/api/users')
    expect(routes[0].framework).toBe('nextjs_app')
  })

  it('extracts multiple HTTP method exports', () => {
    const files = [
      makeFile('src/app/api/items/route.ts', `
export async function GET(request: Request) {
  return Response.json([])
}

export async function POST(request: Request) {
  const body = await request.json()
  return Response.json({ created: true })
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(2)
    expect(routes.map(r => r.methods[0]).sort()).toEqual(['GET', 'POST'])
  })

  it('handles dynamic segments [id] → :id', () => {
    const files = [
      makeFile('src/app/api/users/[id]/route.ts', `
export async function GET(request: Request, { params }: { params: { id: string } }) {
  return Response.json({ id: params.id })
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    expect(routes[0].path).toBe('/api/users/:id')
  })

  it('handles catch-all [...slug]', () => {
    const files = [
      makeFile('src/app/api/docs/[...slug]/route.ts', `
export async function GET() {
  return Response.json({})
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    expect(routes[0].path).toBe('/api/docs/:slug*')
  })

  it('strips route groups from path', () => {
    const files = [
      makeFile('src/app/(dashboard)/api/settings/route.ts', `
export async function GET() {
  return Response.json({})
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    expect(routes[0].path).toBe('/api/settings')
  })

  it('detects protected route groups', () => {
    const files = [
      makeFile('src/app/(authenticated)/api/profile/route.ts', `
export async function GET() {
  return Response.json({})
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    // Route hierarchy should detect (authenticated) group
    expect(routes[0].authMiddleware.length).toBeGreaterThan(0)
  })

  it('extracts Pages Router default export', () => {
    const files = [
      makeFile('src/pages/api/search.ts', `
export default function handler(req, res) {
  if (req.method === 'GET') {
    const q = req.query.q
    res.json({ results: [] })
  }
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    expect(routes[0].framework).toBe('nextjs_pages')
    expect(routes[0].path).toBe('/api/search')
    expect(routes[0].methods).toEqual(['GET'])
  })

  it('detects input sources in App Router', () => {
    const files = [
      makeFile('src/app/api/items/route.ts', `
export async function POST(request: Request) {
  const body = await request.json()
  const url = new URL(request.url)
  const page = url.searchParams.get('page')
  return Response.json({ ok: true })
}
`),
    ]
    const routes = extractNextJSRoutes(files, 'nextjs')
    expect(routes).toHaveLength(1)
    const sources = routes[0].inputs.map(i => i.source)
    expect(sources).toContain('body')
    expect(sources).toContain('query')
  })

  it('skips non-nextjs frameworks', () => {
    const files = [
      makeFile('src/app/api/test/route.ts', `export function GET() {}`),
    ]
    const routes = extractNextJSRoutes(files, 'express')
    expect(routes).toHaveLength(0)
  })
})
