/**
 * Integration tests for the scoring system
 */

import { scoreFindings, DEPTH_CONFIGS } from '../../score'
import type { Vulnerability } from '../../shared/types'
import type { ContextEngineResult } from '../../model/taint-types'

const PROJECT_CONTEXT: ContextEngineResult = {
  projectContext: {
    summary: 'Test project',
    auth: {
      hasGlobalMiddleware: false,
      authProvider: null,
      protectedPaths: [],
      publicPaths: [],
      throwingHelpers: [],
    },
    dataAccess: {
      orm: null,
      hasRLS: false,
    },
    frameworks: {
      primary: null,
      usesTypeScript: true,
    },
    secrets: {
      hasEnvConfig: false,
      secretPatterns: [],
    },
  } as any,
  fileTaintAnalyses: new Map(),
}

function makeFinding(overrides: Partial<Vulnerability> = {}): Vulnerability {
  return {
    id: 'test-1',
    filePath: 'src/app.ts',
    lineNumber: 10,
    lineContent: 'const x = 1',
    severity: 'medium',
    category: 'hardcoded_secret',
    title: 'Test finding',
    description: 'Test',
    confidence: 'medium',
    layer: 1,
    baseConfidence: 0.50,
    ...overrides,
  }
}

describe('scoreFindings', () => {
  it('scores a batch of findings', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1', baseConfidence: 0.70, category: 'hardcoded_secret' }),
      makeFinding({ id: 'f2', baseConfidence: 0.30, category: 'high_entropy_string' }),
      makeFinding({ id: 'f3', baseConfidence: 0.15, category: 'ai_pattern' }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)

    expect(scored).toHaveLength(3)
    // Each finding has a confidence_score
    for (const s of scored) {
      expect(s.confidence_score).toBeDefined()
      expect(s.confidence_score.score).toBeGreaterThanOrEqual(0)
      expect(s.confidence_score.score).toBeLessThanOrEqual(1)
      expect(['surface', 'validate', 'suppress']).toContain(s.confidence_score.routing)
    }
  })

  it('all findings get valid confidence_score', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1' }),
      makeFinding({ id: 'f2', baseConfidence: undefined }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)

    expect(scored[0].confidence_score.base).toBe(0.50)
    expect(scored[1].confidence_score.base).toBe(0.35) // default
  })

  it('test file findings get negative adjustments', () => {
    const findings: Vulnerability[] = [
      makeFinding({
        id: 'f1',
        baseConfidence: 0.50,
        filePath: 'src/__tests__/auth.test.ts',
      }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)

    expect(scored[0].confidence_score.adjustments.length).toBeGreaterThan(0)
    expect(scored[0].confidence_score.score).toBeLessThan(0.50)
    // test_file rule gives -0.35, so 0.50 - 0.35 = 0.15 (may also get scanner_code)
    const testFileAdj = scored[0].confidence_score.adjustments.find(a => a.factor === 'test_file')
    expect(testFileAdj).toBeDefined()
    expect(testFileAdj!.delta).toBe(-0.35)
  })

  it('experimental-equivalent detectors route to suppress', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1', baseConfidence: 0.15, category: 'ai_pattern' }),
      makeFinding({ id: 'f2', baseConfidence: 0.10, category: 'security_bypass' }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)

    // 0.15 < validateThreshold(0.20) → suppress
    expect(scored[0].confidence_score.routing).toBe('suppress')
    // 0.10 < validateThreshold(0.20) → suppress
    expect(scored[1].confidence_score.routing).toBe('suppress')
  })

  it('high-confidence findings route to surface', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1', baseConfidence: 0.70, category: 'hardcoded_secret' }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)
    expect(scored[0].confidence_score.routing).toBe('surface')
  })

  it('medium-confidence findings route to validate in verified depth', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1', baseConfidence: 0.50, category: 'config_audit' }),
    ]

    const { scored } = scoreFindings(findings, 'verified', PROJECT_CONTEXT)
    expect(scored[0].confidence_score.routing).toBe('validate')
  })

  it('local depth only surfaces high-confidence findings', () => {
    const findings: Vulnerability[] = [
      makeFinding({ id: 'f1', baseConfidence: 0.70 }),
      makeFinding({ id: 'f2', baseConfidence: 0.50 }),
      makeFinding({ id: 'f3', baseConfidence: 0.20 }),
    ]

    const { scored } = scoreFindings(findings, 'local', PROJECT_CONTEXT)

    expect(scored[0].confidence_score.routing).toBe('surface')
    expect(scored[1].confidence_score.routing).toBe('suppress') // No AI in local
    expect(scored[2].confidence_score.routing).toBe('suppress')
  })
})

describe('DEPTH_CONFIGS', () => {
  it('local has AI disabled', () => {
    expect(DEPTH_CONFIGS.local.aiEnabled).toBe(false)
    expect(DEPTH_CONFIGS.local.surfaceThreshold).toBe(0.70)
  })

  it('verified has AI enabled', () => {
    expect(DEPTH_CONFIGS.verified.aiEnabled).toBe(true)
    expect(DEPTH_CONFIGS.verified.validateThreshold).toBe(0.20)
  })

  it('deep has lowest validate threshold', () => {
    expect(DEPTH_CONFIGS.deep.aiEnabled).toBe(true)
    expect(DEPTH_CONFIGS.deep.validateThreshold).toBe(0.10)
  })
})
