/**
 * Framework Analysis Orchestrator
 *
 * Runs applicable framework security models against each file,
 * returning per-file framework analysis results (safe/unsafe line annotations).
 */

import type { ScanFile } from '../../shared/types'
import type { ProjectContext } from '../project-context'
import type { FrameworkSecurityModel, FileFrameworkAnalysis, FrameworkSafePattern, FrameworkUnsafePattern } from './types'
import { reactModel } from './react'
import { nextjsModel } from './nextjs'
import { expressModel } from './express'
import { djangoModel } from './django'
import { sequelizeModel } from './sequelize'
import { prismaModel } from './prisma'

/**
 * Select applicable framework models based on project context.
 */
function selectModels(projectContext: ProjectContext): FrameworkSecurityModel[] {
  const models: FrameworkSecurityModel[] = []

  if (projectContext.frameworks.frontend === 'react') {
    models.push(reactModel)
  }
  if (projectContext.frameworks.primary === 'nextjs') {
    models.push(nextjsModel)
    // Next.js uses React — ensure React model is included
    if (!models.some(m => m.framework === 'react')) {
      models.push(reactModel)
    }
  }
  if (projectContext.frameworks.primary === 'express') {
    models.push(expressModel)
  }
  if (projectContext.frameworks.primary === 'django') {
    models.push(djangoModel)
  }

  // ORM-specific models
  if (projectContext.dataAccess.orm === 'sequelize') {
    models.push(sequelizeModel)
  }
  if (projectContext.dataAccess.orm === 'prisma') {
    models.push(prismaModel)
  }

  return models
}

/**
 * Analyze framework patterns across all files.
 *
 * For each file, runs all applicable framework models against each line.
 * Returns a Map of file path → FileFrameworkAnalysis.
 *
 * Only files with at least one match are included in the result.
 */
export function analyzeFrameworkPatterns(
  files: ScanFile[],
  projectContext: ProjectContext
): Map<string, FileFrameworkAnalysis> {
  const models = selectModels(projectContext)
  if (models.length === 0) return new Map()

  const results = new Map<string, FileFrameworkAnalysis>()

  for (const file of files) {
    const safeLines = new Map<number, FrameworkSafePattern[]>()
    const unsafeLines = new Map<number, FrameworkUnsafePattern[]>()
    const lines = file.content.split('\n')

    for (let i = 0; i < lines.length; i++) {
      const lineContent = lines[i]
      const lineNumber = i + 1

      for (const model of models) {
        for (const safe of model.safePatterns) {
          if (safe.detect(lineContent, file.path, file.content)) {
            const existing = safeLines.get(lineNumber)
            if (existing) {
              // Avoid duplicate IDs on the same line
              if (!existing.some(p => p.id === safe.id)) {
                existing.push(safe)
              }
            } else {
              safeLines.set(lineNumber, [safe])
            }
          }
        }
        for (const unsafe of model.unsafePatterns) {
          if (unsafe.detect(lineContent, file.path, file.content)) {
            const existing = unsafeLines.get(lineNumber)
            if (existing) {
              if (!existing.some(p => p.id === unsafe.id)) {
                existing.push(unsafe)
              }
            } else {
              unsafeLines.set(lineNumber, [unsafe])
            }
          }
        }
      }
    }

    if (safeLines.size > 0 || unsafeLines.size > 0) {
      results.set(file.path, { safeLines, unsafeLines })
    }
  }

  return results
}

// Re-export types
export type { FrameworkSecurityModel, FrameworkSafePattern, FrameworkUnsafePattern, FileFrameworkAnalysis } from './types'
