/**
 * Layer 2: Logic Gates Detection
 * Identifies security bypass patterns and dangerous logic flows
 */

import type { Vulnerability } from '../../shared/types'
import type { ParsedFile } from '../../shared/parsed-file'
import { isScannerOrFixtureFile } from '../../parse/file-classifier'
import { isDisabledAuthComment } from '../../shared/comment-analyzer'
import { isReactStateSetter, isActualRedirect } from '../../shared/intent-detector'

const BASE_CONFIDENCE = 0.20

interface LogicPattern {
  name: string
  pattern: RegExp
  severity: 'critical' | 'high' | 'medium' | 'low'
  description: string
  suggestedFix: string
}

// Patterns for security bypass logic
const LOGIC_PATTERNS: LogicPattern[] = [
  // Development mode bypasses
  {
    name: 'Development mode security bypass',
    pattern: /if\s*\(\s*process\.env\.NODE_ENV\s*[!=]==?\s*['"]production['"]\s*\)\s*(return\s+true|return\s*;|continue|break)/gi,
    severity: 'high',
    description: 'Security check bypassed in non-production environments',
    suggestedFix: 'Remove development-only bypasses or ensure they cannot be triggered in production',
  },
  {
    name: 'Development mode auth skip',
    pattern: /if\s*\(\s*process\.env\.NODE_ENV\s*[!=]==?\s*['"]development['"]\s*\)/gi,
    severity: 'medium',
    description: 'Code path that only runs in development - verify no security implications',
    suggestedFix: 'Ensure this development-only code does not bypass security controls',
  },
  // Auth bypasses
  {
    name: 'Authentication bypass pattern',
    pattern: /if\s*\(\s*(true|1|!false)\s*\)\s*{\s*(return|next|resolve)/gi,
    severity: 'critical',
    description: 'Hardcoded truthy condition may bypass authentication',
    suggestedFix: 'Remove hardcoded bypass and implement proper authentication check',
  },
  // NOTE: 'Commented auth check' pattern has been replaced with smart comment analysis
  // The isDisabledAuthComment() function distinguishes explanatory comments from disabled code
  // This is handled specially in detectLogicGates() below
  // Skip validation patterns
  {
    name: 'Validation skip',
    pattern: /skipValidation\s*[=:]\s*true|validate\s*[=:]\s*false|noValidate\s*[=:]\s*true/gi,
    severity: 'high',
    description: 'Input validation explicitly disabled',
    suggestedFix: 'Enable validation or ensure this is intentional and documented',
  },
  // Debug/test bypasses
  {
    name: 'Debug bypass',
    pattern: /if\s*\(\s*(DEBUG|TEST|SKIP_AUTH|BYPASS|DISABLE_AUTH)\s*\)/gi,
    severity: 'high',
    description: 'Debug/test flag may bypass security controls',
    suggestedFix: 'Remove debug bypasses before deploying to production',
  },
  // Unsafe defaults
  {
    name: 'Unsafe default allow',
    pattern: /default\s*:\s*(return\s+true|allow|permit|grant)/gi,
    severity: 'medium',
    description: 'Default case allows access - should default to deny',
    suggestedFix: 'Change default behavior to deny access (fail-safe defaults)',
  },
  // Empty catch blocks
  {
    name: 'Empty error handler',
    pattern: /catch\s*\([^)]*\)\s*{\s*(\/\/.*)?}/gi,
    severity: 'medium',
    description: 'Empty catch block may hide security errors',
    suggestedFix: 'Log the error or handle it appropriately',
  },
  // Disabled security features
  {
    name: 'Disabled CSRF protection',
    pattern: /csrf\s*[=:]\s*false|disableCsrf|csrfProtection\s*[=:]\s*false/gi,
    severity: 'high',
    description: 'CSRF protection explicitly disabled',
    suggestedFix: 'Enable CSRF protection for state-changing requests',
  },
  {
    name: 'Disabled SSL verification',
    pattern: /rejectUnauthorized\s*[=:]\s*false|verify\s*[=:]\s*false|ssl\s*[=:]\s*false|NODE_TLS_REJECT_UNAUTHORIZED/gi,
    severity: 'critical',
    description: 'SSL/TLS certificate verification disabled',
    suggestedFix: 'Enable SSL verification to prevent man-in-the-middle attacks',
  },
  // Insecure comparisons - ONLY flag actual secret comparisons
  // Timing attacks are only relevant when comparing cryptographic secrets
  // Do NOT flag: error codes, UI state, null checks, empty strings, route IDs, type checks
  {
    name: 'Timing attack vulnerable comparison',
    // Only match explicit secret-related variable names being compared with ===
    // This avoids flagging general string comparisons which are not timing-sensitive
    pattern: /\b(password|secret|token|apiKey|api_key|credential|hash|digest|signature|privateKey|private_key|secretKey|secret_key)\s*===?\s*['"][^'"]+['"]/gi,
    severity: 'medium',
    description: 'Direct comparison of secret value may be vulnerable to timing attacks',
    suggestedFix: 'Use constant-time comparison for secrets (e.g., crypto.timingSafeEqual)',
  },
  // Unsafe redirects - NOTE: Now uses intent detection to distinguish from React state setters
  // The pattern is checked, but isReactStateSetter() is used to skip false positives
  {
    name: 'Open redirect vulnerability',
    pattern: /redirect\s*\(\s*(req\.(query|params|body)\.|request\.|url\.)/gi,
    severity: 'high',
    description: 'Redirect URL from user input may allow open redirect attacks',
    suggestedFix: 'Validate redirect URLs against an allowlist of trusted domains',
  },
  // Admin/superuser bypasses
  {
    name: 'Admin bypass pattern',
    pattern: /if\s*\(\s*(isAdmin|isSuperUser|isRoot|role\s*===?\s*['"]admin['"])\s*\)\s*(return|continue|break)/gi,
    severity: 'medium',
    description: 'Admin role bypasses normal security checks',
    suggestedFix: 'Ensure admin bypass is intentional and properly audited',
  },
]

// Check if line is a comment
function isComment(line: string): boolean {
  const trimmed = line.trim()
  return (
    trimmed.startsWith('//') ||
    trimmed.startsWith('#') ||
    trimmed.startsWith('*') ||
    trimmed.startsWith('/*')
  )
}

export function detectLogicGates(
  content: string,
  filePath: string,
  options?: { parsed?: ParsedFile }
): Vulnerability[] {
  const vulnerabilities: Vulnerability[] = []

  // Skip scanner/fixture files to avoid self-detection
  if (isScannerOrFixtureFile(filePath)) return vulnerabilities

  const lines = options?.parsed?.lines ?? content.split('\n')

  // Check each line against patterns
  lines.forEach((line, index) => {
    // Skip comment lines (handled separately below for auth comments)
    if (isComment(line)) {
      return
    }

    for (const logicPattern of LOGIC_PATTERNS) {
      const regex = new RegExp(logicPattern.pattern.source, logicPattern.pattern.flags)

      if (regex.test(line)) {
        // Special handling for redirect patterns - check if it's actually a React state setter
        if (logicPattern.name === 'Open redirect vulnerability') {
          if (isReactStateSetter(line)) {
            // This is a React state setter like setState(), not a redirect
            continue
          }
          if (!isActualRedirect(line)) {
            // This doesn't look like an actual redirect function
            continue
          }
        }

        vulnerabilities.push({
          id: `logic-${filePath}-${index + 1}-${logicPattern.name}`,
          filePath,
          lineNumber: index + 1,
          lineContent: line.trim(),
          severity: logicPattern.severity,
          category: 'security_bypass',
          title: logicPattern.name,
          description: logicPattern.description,
          suggestedFix: logicPattern.suggestedFix,
          confidence: 'medium',
          baseConfidence: BASE_CONFIDENCE,
          layer: 2,
        source: 'structural' as const,
        })
        break // Only report once per line
      }
    }
  })

  // Smart comment analysis for disabled auth patterns
  // Only flag comments that are genuinely disabled code, not explanatory comments
  lines.forEach((line, index) => {
    // Check if this is a comment line with auth-related content
    if (isComment(line) && /auth|permission|verify|check|token/i.test(line)) {
      // Use smart analysis to determine if this is disabled code
      if (isDisabledAuthComment(lines, index)) {
        vulnerabilities.push({
          id: `logic-${filePath}-${index + 1}-commented-auth-check`,
          filePath,
          lineNumber: index + 1,
          lineContent: line.trim(),
          severity: 'high',
          category: 'security_bypass',
          title: 'Commented auth check',
          description: 'Commented out authentication/authorization code detected. This may indicate disabled security controls.',
          suggestedFix: 'Remove commented code or restore the security check',
          confidence: 'medium',
          baseConfidence: BASE_CONFIDENCE,
          layer: 2,
        source: 'structural' as const,
        })
      }
    }
  })

  // Multi-line pattern detection (for more complex patterns)
  const multiLineFindings = detectMultiLinePatterns(content, filePath)
  vulnerabilities.push(...multiLineFindings)

  return vulnerabilities
}

// Detect patterns that span multiple lines
function detectMultiLinePatterns(content: string, filePath: string): Vulnerability[] {
  const vulnerabilities: Vulnerability[] = []
  const lines = content.split('\n')

  // Detect try-catch with empty or minimal error handling
  const tryCatchPattern = /try\s*{[\s\S]*?}\s*catch\s*\([^)]*\)\s*{\s*(\n\s*)*(\/\/[^\n]*)?\s*}/g
  let match

  while ((match = tryCatchPattern.exec(content)) !== null) {
    const lineNumber = content.substring(0, match.index).split('\n').length
    vulnerabilities.push({
      id: `logic-multiline-${filePath}-${lineNumber}`,
      filePath,
      lineNumber,
      lineContent: lines[lineNumber - 1]?.trim() || 'try {',
      severity: 'medium',
      category: 'security_bypass',
      title: 'Silent error handling',
      description: 'Try-catch block with minimal error handling may hide security issues',
      suggestedFix: 'Log errors appropriately and handle them based on type',
      confidence: 'low',
      baseConfidence: BASE_CONFIDENCE,
      layer: 2,
        source: 'structural' as const,
    })
  }

  return vulnerabilities
}
