import { extractExpressRoutes, extractMountPoints } from '../../../model/route-discovery/express'

describe('Express Route Extractor', () => {
  describe('extractExpressRoutes', () => {
    it('extracts app.get route', () => {
      const content = `
const express = require('express')
const app = express()
app.get('/api/users', getUsers)
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(1)
      expect(routes[0].methods).toEqual(['GET'])
      expect(routes[0].path).toBe('/api/users')
      expect(routes[0].framework).toBe('express')
    })

    it('extracts router.post route', () => {
      const content = `
const router = require('express').Router()
router.post('/api/items', createItem)
`
      const routes = extractExpressRoutes(content, 'src/routes.js')
      expect(routes).toHaveLength(1)
      expect(routes[0].methods).toEqual(['POST'])
      expect(routes[0].path).toBe('/api/items')
    })

    it('detects multi-middleware route', () => {
      const content = `
const app = require('express')()
app.post('/api/data', authMiddleware, validateBody, handleData)
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(1)
      expect(routes[0].authMiddleware).toContain('authMiddleware')
    })

    it('detects rate limiting middleware', () => {
      const content = `
const app = require('express')()
app.get('/api/search', rateLimiter, searchHandler)
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(1)
      expect(routes[0].rateLimiting).toBe(true)
    })

    it('detects public endpoints', () => {
      const content = `
const app = require('express')()
app.get('/health', healthCheck)
app.get('/healthz', healthCheck)
app.get('/ready', readyCheck)
app.get('/ping', pingHandler)
app.get('/status', statusHandler)
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(5)
      routes.forEach(r => expect(r.isPublic).toBe(true))
    })

    it('detects input sources from handler body', () => {
      const content = `
const app = require('express')()
app.post('/api/users', async (req, res) => {
  const { name, email } = req.body
  const page = req.query.page
  const id = req.params.id
  res.json({ ok: true })
})
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(1)
      const sources = routes[0].inputs.map(i => i.source)
      expect(sources).toContain('body')
      expect(sources).toContain('query')
      expect(sources).toContain('params')
    })

    it('extracts multiple routes in one file', () => {
      const content = `
const app = require('express')()
app.get('/api/users', listUsers)
app.post('/api/users', createUser)
app.delete('/api/users', deleteUser)
`
      const routes = extractExpressRoutes(content, 'src/server.js')
      expect(routes).toHaveLength(3)
      expect(routes.map(r => r.methods[0])).toEqual(['GET', 'POST', 'DELETE'])
    })

    it('detects Fastify preHandler route', () => {
      const content = `
import Fastify from 'fastify'
const server = Fastify()
server.route({
  method: 'GET',
  url: '/api/data',
  preHandler: [authenticate, rateLimit],
  handler: getData
})
`
      const routes = extractExpressRoutes(content, 'src/server.ts')
      expect(routes).toHaveLength(1)
      expect(routes[0].framework).toBe('fastify')
      expect(routes[0].methods).toEqual(['GET'])
      expect(routes[0].path).toBe('/api/data')
      expect(routes[0].authMiddleware).toContain('authenticate')
    })

    it('detects Hono routes', () => {
      const content = `
import { Hono } from 'hono'
const app = new Hono()
app.get('/api/hello', (c) => {
  return c.json({ message: 'hello' })
})
`
      const routes = extractExpressRoutes(content, 'src/server.ts')
      expect(routes).toHaveLength(1)
      expect(routes[0].framework).toBe('hono')
    })
  })

  describe('extractMountPoints', () => {
    it('extracts path-scoped mount', () => {
      const content = `
const app = require('express')()
app.use('/api', authMiddleware)
`
      const mounts = extractMountPoints(content, 'src/server.js')
      expect(mounts).toHaveLength(1)
      expect(mounts[0].path).toBe('/api')
      expect(mounts[0].middleware).toContain('authMiddleware')
      expect(mounts[0].isGlobal).toBe(false)
    })

    it('extracts global mount', () => {
      const content = `
const app = require('express')()
app.use(helmet())
`
      const mounts = extractMountPoints(content, 'src/server.js')
      expect(mounts).toHaveLength(1)
      expect(mounts[0].isGlobal).toBe(true)
      expect(mounts[0].middleware).toContain('helmet')
    })
  })
})
