/**
 * Next.js App Router analyzer
 * Analyzes route handlers in app directory
 */

import * as fs from 'fs'
import * as path from 'path'
import { exportToJSON } from '../export.js'
import { uploadRoutes } from '../uploader.js'

export interface NextAppRoute {
    method: string
    path: string
    description: string
    tags: string[]
    middleware: string[]
    parameters?: any[]
    responses: Record<string, any>
}

export interface AnalyzerOptions {
    projectName: string
    appDir?: string
    saveJson?: boolean
    jsonPath?: string
    upload?: boolean
    apiKey?: string
    apiForgeUrl?: string
    baseUrl?: string
}

/**
 * Analyze Next.js App Router routes
 */
export async function analyzeNextApp(options: AnalyzerOptions | string = 'app'): Promise<NextAppRoute[]> {
    // Support both string path and options object
    const appDir = typeof options === 'string' ? options : (options.appDir || 'app')
    const opts: AnalyzerOptions = typeof options === 'string' ? { projectName: '' } as AnalyzerOptions : options

    const routes: NextAppRoute[] = []

    try {
        const baseDir = path.join(process.cwd(), appDir)

        if (!fs.existsSync(baseDir)) {
            console.warn('app directory not found')
            return routes
        }

        // Recursively scan for route.ts/route.js files
        const scanDir = (dir: string, basePath: string = '') => {
            const entries = fs.readdirSync(dir, { withFileTypes: true })

            for (const entry of entries) {
                const fullPath = path.join(dir, entry.name)

                if (entry.isDirectory()) {
                    // Handle dynamic routes like [id]
                    const dirName = entry.name.startsWith('[') && entry.name.endsWith(']')
                        ? `:${entry.name.slice(1, -1)}`
                        : entry.name

                    // Skip non-route directories
                    if (['_components', '_lib', '_utils'].includes(entry.name)) {
                        continue
                    }

                    scanDir(fullPath, `${basePath}/${dirName}`)
                } else if (entry.isFile() && /route\.(ts|js)$/.test(entry.name)) {
                    // Found a route file
                    const content = fs.readFileSync(fullPath, 'utf-8')
                    const methods = detectAppRouterMethods(content)

                    methods.forEach(method => {
                        routes.push({
                            method,
                            path: basePath || '/',
                            description: `${method} ${basePath || '/'}`,
                            tags: basePath.startsWith('/api') ? ['api'] : ['app'],
                            middleware: detectMiddleware(content),
                            parameters: extractParameters(basePath),
                            responses: {
                                '200': { description: 'Successful response' }
                            }
                        })
                    })
                }
            }
        }

        scanDir(baseDir)

        console.log(`✅ Found ${routes.length} routes`)

        // Export to JSON if requested
        if (opts.saveJson && opts.projectName) {
            const filePath = opts.jsonPath || 'api-export.json'
            await exportToJSON(routes, opts.projectName, filePath, opts.baseUrl)
        }

        // Upload to APIForge if requested
        if (opts.upload && opts.apiKey && opts.projectName) {
            await uploadRoutes(routes, {
                projectName: opts.projectName,
                apiKey: opts.apiKey,
                baseUrl: opts.baseUrl,
                apiForgeUrl: opts.apiForgeUrl
            })
        }

    } catch (error: any) {
        console.error('Error analyzing Next.js App routes:', error.message)
    }

    return routes
}

/**
 * Detect exported HTTP method handlers
 */
function detectAppRouterMethods(content: string): string[] {
    const methods: string[] = []
    const httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']

    httpMethods.forEach(method => {
        // Check for export async function METHOD or export function METHOD
        const regex = new RegExp(`export\\s+(async\\s+)?function\\s+${method}\\s*\\(`, 'g')
        if (regex.test(content)) {
            methods.push(method)
        }
    })

    return methods
}

/**
 * Detect middleware usage
 */
function detectMiddleware(content: string): string[] {
    const middleware: string[] = []

    if (content.includes('auth') || content.includes('authenticate')) {
        middleware.push('auth')
    }
    if (content.includes('cors')) {
        middleware.push('cors')
    }

    return middleware
}

/**
 * Extract parameters from route path
 */
function extractParameters(routePath: string): any[] {
    const params: any[] = []
    const paramMatches = routePath.match(/:(\w+)/g) || []

    paramMatches.forEach(param => {
        const name = param.slice(1)
        params.push({
            name,
            in: 'path',
            required: true,
            type: 'string',
            description: `Path parameter: ${name}`
        })
    })

    return params
}
