/**
 * Imported Auth Detector
 *
 * Detects auth middleware/helpers imported from other files to avoid
 * false positives on routes that are actually protected via imports.
 *
 * Example: A route file that does `import { authMiddleware } from '@/lib/auth'`
 * and wraps handlers with it should not be flagged as "missing auth".
 */

import type { ScanFile } from '../shared/types'
import { extractAllImports } from './import-resolver'
import type { ParsedImport } from './import-resolver'
import { escapeRegex } from './sink-patterns'

// ============================================================================
// Types
// ============================================================================

export interface ImportedAuthInfo {
  importPath: string           // '@/lib/auth' or './middleware'
  importedNames: string[]      // ['authMiddleware', 'requireAuth']
  isAuthRelated: boolean       // Based on name patterns
}

export interface FileAuthImports {
  filePath: string
  imports: ImportedAuthInfo[]
  usesImportedAuth: boolean    // Does the file actually use imported auth?
}

// ============================================================================
// Patterns
// ============================================================================

/**
 * Patterns that indicate auth-related imports by name
 */
const AUTH_NAME_PATTERNS = [
  /auth/i,
  /middleware/i,
  /protect/i,
  /guard/i,
  /session/i,
  /verify/i,
  /secure/i,
  /jwt/i,
  /token/i,
]

/**
 * Specific auth import names commonly used
 */
const KNOWN_AUTH_IMPORTS = new Set([
  // Next.js / NextAuth
  'auth',
  'getServerSession',
  'getSession',
  'withAuth',
  'getToken',
  'NextAuth',
  'NextAuthOptions',

  // Clerk
  'auth',
  'currentUser',
  'clerkMiddleware',
  'getAuth',
  'SignedIn',
  'SignedOut',

  // Auth0
  'withPageAuthRequired',
  'withApiAuthRequired',
  'getSession',
  'getAccessToken',

  // Custom auth patterns
  'authMiddleware',
  'requireAuth',
  'requireAuthentication',
  'checkAuth',
  'verifyAuth',
  'protectRoute',
  'withAuthentication',
  'authenticated',
  'getCurrentUser',
  'getCurrentUserId',
  'getUser',
  'getUserId',
])

/**
 * Patterns indicating auth-related import paths
 */
const AUTH_PATH_PATTERNS = [
  /\/auth\//i,
  /\/middleware/i,
  /\/lib\/auth/i,
  /\/utils\/auth/i,
  /\/helpers\/auth/i,
  /next-auth/i,
  /@clerk/i,
  /@auth0/i,
  /lucia/i,
]

// ============================================================================
// Import Extraction
// ============================================================================

/**
 * Extract all imports from a file's content and classify them as auth-related.
 * Delegates to the shared extractAllImports() for parsing, then applies auth filters.
 */
export function extractImports(content: string): ImportedAuthInfo[] {
  const allImports = extractAllImports(content, '')

  return allImports
    .filter(imp => !imp.isReExport)
    .map((imp: ParsedImport) => {
      // For default imports, use the original local name (first importedName)
      const names = imp.importedNames[0] === 'default'
        ? imp.importedNames
        : imp.importedNames

      return {
        importPath: imp.importPath,
        importedNames: names,
        isAuthRelated: isAuthRelatedImport(names, imp.importPath),
      }
    })
}

/**
 * Check if an import is auth-related based on names and path
 */
function isAuthRelatedImport(names: string[], importPath: string): boolean {
  // Check if path is auth-related
  if (AUTH_PATH_PATTERNS.some(p => p.test(importPath))) {
    return true
  }

  // Check if any imported name is auth-related
  for (const name of names) {
    // Known auth imports
    if (KNOWN_AUTH_IMPORTS.has(name)) {
      return true
    }

    // Pattern-based detection
    if (AUTH_NAME_PATTERNS.some(p => p.test(name))) {
      return true
    }
  }

  return false
}

// ============================================================================
// Auth Usage Detection
// ============================================================================

/**
 * Check if imported auth is actually used to protect routes/handlers
 */
export function detectImportedAuthUsage(
  content: string,
  authImports: ImportedAuthInfo[]
): boolean {
  if (authImports.length === 0) return false

  const authNames = authImports.flatMap(imp => imp.importedNames)

  for (const name of authNames) {
    // Pattern 1: Handler wrapping - export const GET = authMiddleware(...)
    const wrapperPattern = new RegExp(
      `(?:export\\s+(?:const|function)\\s+(?:GET|POST|PUT|PATCH|DELETE|handler)\\s*=\\s*${escapeRegex(name)}\\s*\\()` +
      `|(?:${escapeRegex(name)}\\s*\\(\\s*(?:async\\s+)?(?:function|\\())`
    )
    if (wrapperPattern.test(content)) {
      return true
    }

    // Pattern 2: Middleware chain - app.use(authMiddleware)
    const middlewareChainPattern = new RegExp(
      `\\.(?:use|all|get|post|put|patch|delete)\\s*\\([^)]*${escapeRegex(name)}`
    )
    if (middlewareChainPattern.test(content)) {
      return true
    }

    // Pattern 3: Express/Fastify route with middleware - router.get('/', requireAuth, handler)
    const routeMiddlewarePattern = new RegExp(
      `\\.(?:get|post|put|patch|delete)\\s*\\([^,]+,\\s*${escapeRegex(name)}`
    )
    if (routeMiddlewarePattern.test(content)) {
      return true
    }

    // Pattern 4: HOC pattern - withAuth(Component)
    const hocPattern = new RegExp(`${escapeRegex(name)}\\s*\\(\\s*\\w+\\s*\\)`)
    if (hocPattern.test(content)) {
      return true
    }

    // Pattern 5: Auth function call at top of handler - const session = await auth()
    const authCallPattern = new RegExp(
      `(?:await\\s+)?${escapeRegex(name)}\\s*\\(\\s*\\)` +
      `|${escapeRegex(name)}\\s*\\(\\s*(?:req|request|ctx|context)\\s*[,)]`
    )
    if (authCallPattern.test(content)) {
      return true
    }
  }

  return false
}

// ============================================================================
// Registry Builder
// ============================================================================

/**
 * Build a registry of files and their auth imports
 */
export function buildFileAuthImports(files: ScanFile[]): Map<string, FileAuthImports> {
  const registry = new Map<string, FileAuthImports>()

  for (const file of files) {
    const allImports = extractImports(file.content)
    const authImports = allImports.filter(imp => imp.isAuthRelated)

    const usesImportedAuth =
      authImports.length > 0 &&
      detectImportedAuthUsage(file.content, authImports)

    registry.set(file.path, {
      filePath: file.path,
      imports: authImports,
      usesImportedAuth,
    })
  }

  return registry
}

/**
 * Check if a specific file uses imported auth protection
 */
export function fileUsesImportedAuth(
  filePath: string,
  registry: Map<string, FileAuthImports>
): boolean {
  return registry.get(filePath)?.usesImportedAuth ?? false
}
