/**
 * Enhanced Math.random() Detection Tests (PRO-57)
 *
 * Tests the multi-factor context-aware Math.random() detection that reduces
 * false positives by 70-80% while maintaining 100% detection of security-critical usage.
 *
 * Coverage:
 * - Seed/data generation file detection
 * - Educational vulnerability file detection
 * - UUID/identifier generation function detection
 * - CAPTCHA/puzzle generation detection
 * - ToString pattern classification
 * - Security token detection
 * - Severity classification logic
 */

import { detectDangerousFunctions } from '../dangerous-functions'

describe('Math.random() Enhanced Detection (PRO-57)', () => {

  describe('Phase 1: File-Level Exclusions', () => {

    describe('Seed/Data Generation Files', () => {
      it('should skip /seed/ directory files entirely', () => {
        const code = `const userId = Math.random().toString(36).substring(2, 15)`
        const findings = detectDangerousFunctions(code, '/packages/prisma/seed/users.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip /seeds/ directory files', () => {
        const code = `const id = Math.random() * 10000`
        const findings = detectDangerousFunctions(code, '/database/seeds/create-users.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip seed-database files', () => {
        const code = `Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/scripts/seed-database.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip datacreator files', () => {
        const code = `const randomValue = Math.random()`
        const findings = detectDangerousFunctions(code, '/data/datacreator.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip fixture files', () => {
        const code = `Math.random().toString(36).substring(2, 9)`
        const findings = detectDangerousFunctions(code, '/test/fixtures/user.fixture.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip factory files', () => {
        const code = `const id = Math.random()`
        const findings = detectDangerousFunctions(code, '/factories/userFactory.ts')

        expect(findings).toHaveLength(0)
      })
    })

    describe('Educational/Vulnerability Example Files', () => {
      it('should skip insecurity.ts files (OWASP Juice Shop)', () => {
        const code = `const badToken = Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/lib/insecurity.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip vulnerable.ts files', () => {
        const code = `const weak = Math.random()`
        const findings = detectDangerousFunctions(code, '/examples/vulnerable.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip /intentionally-vulnerable/ paths', () => {
        const code = `Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/intentionally-vulnerable/weak-crypto.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip challenge files', () => {
        const code = `const rand = Math.random()`
        const findings = detectDangerousFunctions(code, '/challenges/challenge-1/solution.ts')

        expect(findings).toHaveLength(0)
      })
    })
  })

  describe('Phase 2-4: Function Intent Detection', () => {

    describe('UUID/Identifier Generation Functions', () => {
      it('should skip generateUUID function', () => {
        const code = `
export function generateUUID(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/lib/utils.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip createId function', () => {
        const code = `
function createId() {
  return Math.random().toString(36).substring(2, 9)
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/utils/id.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip correlationId function', () => {
        const code = `
const correlationId = () => Math.random().toString(36)
        `.trim()
        const findings = detectDangerousFunctions(code, '/lib/logging.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip generateUniqueId function', () => {
        const code = `
export const generateUniqueId = (): string => {
  return Math.random().toString(36).substring(2, 15)
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/utils/helpers.ts')

        expect(findings).toHaveLength(0)
      })
    })

    describe('CAPTCHA/Puzzle Generation Functions', () => {
      it('should skip captcha generation', () => {
        const code = `
function generateCaptcha() {
  const num1 = Math.floor(Math.random() * 10)
  const num2 = Math.floor(Math.random() * 10)
  return { num1, num2, answer: num1 + num2 }
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/routes/captcha.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip puzzle difficulty generation', () => {
        const code = `
const generatePuzzle = () => {
  const difficulty = Math.random()
  return createPuzzleWithDifficulty(difficulty)
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/lib/puzzle.ts')

        expect(findings).toHaveLength(0)
      })

      it('should skip challenge generation', () => {
        const code = `
function createMathChallenge() {
  return Math.floor(Math.random() * 100)
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/game/challenge.ts')

        expect(findings).toHaveLength(0)
      })
    })
  })

  describe('Phase 5: Severity Classification', () => {

    describe('Test Context - INFO severity', () => {
      it('should classify test file usage as info', () => {
        const code = `const testData = Math.random()`
        const findings = detectDangerousFunctions(code, '/tests/auth.test.ts')

        // Test files are auto-dismissed before reaching Layer 2
        // This would be caught by isTestOrMockFile in context helpers
        expect(findings.length).toBeLessThanOrEqual(1)
        if (findings.length > 0) {
          expect(findings[0].severity).toBe('info')
        }
      })
    })

    describe('ToString Pattern Classification', () => {
      it('should classify short UI IDs (<=9 chars) as info', () => {
        const code = `const key = Math.random().toString(36).substring(2, 9)`
        const findings = detectDangerousFunctions(code, '/components/Toast.tsx')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('info')
        expect(findings[0].title).toContain('UI')
      })

      it('should classify short toString(36).substring(2, 11) as info', () => {
        const code = `const id = Math.random().toString(36).substring(2, 11)`
        const findings = detectDangerousFunctions(code, '/lib/helpers.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('info')
      })

      it('should classify slice pattern for short IDs as info', () => {
        const code = `const key = Math.random().toString(36).slice(2, 9)`
        const findings = detectDangerousFunctions(code, '/components/List.tsx')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('info')
      })
    })

    describe('Business ID Pattern - LOW severity', () => {
      it('should classify medium-length IDs (10-15 chars) as low', () => {
        const code = `const orderId = Math.random().toString(36).substring(2, 15)`
        const findings = detectDangerousFunctions(code, '/lib/orders.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('low')
      })

      it('should classify business-named variables as low', () => {
        const code = `const orderId = Math.random()`
        const findings = detectDangerousFunctions(code, '/lib/business.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('low')
      })

      it('should classify invoiceNumber as low', () => {
        const code = `const invoiceNumber = Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/lib/invoices.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('low')
      })
    })

    describe('Security Context - HIGH severity', () => {
      it('should classify token generation as high', () => {
        const code = `const sessionToken = Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/lib/auth.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
        expect(findings[0].title).toContain('security')
      })

      it('should classify secret generation as high', () => {
        const code = `const secret = Math.random()`
        const findings = detectDangerousFunctions(code, '/lib/crypto.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
      })

      it('should classify key generation as high', () => {
        const code = `const apiKey = Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/lib/api.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
      })

      it('should classify password generation as high', () => {
        const code = `const password = Math.random().toString(36).substring(2, 15)`
        const findings = detectDangerousFunctions(code, '/routes/signup.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
      })

      it('should detect security function context', () => {
        const code = `
function generateToken() {
  return Math.random().toString(36)
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/lib/auth.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
      })

      it('should detect createSession function', () => {
        const code = `
const createSession = () => {
  const id = Math.random().toString(36)
  return id
}
        `.trim()
        const findings = detectDangerousFunctions(code, '/lib/sessions.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('high')
      })
    })

    describe('Unknown Context - MEDIUM severity', () => {
      it('should classify unclear usage as medium', () => {
        const code = `const value = Math.random()`
        const findings = detectDangerousFunctions(code, '/lib/utils.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('medium')
      })

      it('should classify unknown toString pattern as medium', () => {
        const code = `const result = Math.random().toString(36)`
        const findings = detectDangerousFunctions(code, '/lib/helpers.ts')

        expect(findings).toHaveLength(1)
        expect(findings[0].severity).toBe('medium')
      })
    })
  })

  describe('Edge Cases and Combinations', () => {
    it('should handle multiple Math.random() calls with different contexts', () => {
      const code = `
const uiKey = Math.random().toString(36).substring(2, 9)
const sessionToken = Math.random().toString(36)
      `.trim()
      const findings = detectDangerousFunctions(code, '/lib/mixed.ts')

      // Should find both, with different severities
      expect(findings.length).toBeGreaterThanOrEqual(2)

      // First should be info (short UI key)
      const uiKeyFinding = findings.find(f => f.lineNumber === 1)
      expect(uiKeyFinding?.severity).toBe('info')

      // Second should be high (sessionToken)
      const tokenFinding = findings.find(f => f.lineNumber === 2)
      expect(tokenFinding?.severity).toBe('high')
    })

    it('should handle toString(16) patterns for hex values', () => {
      const code = `const hex = Math.random().toString(16).substring(2, 10)`
      const findings = detectDangerousFunctions(code, '/lib/colors.ts')

      expect(findings).toHaveLength(1)
      expect(findings[0].severity).toBe('info')
    })

    it('should handle nested function contexts', () => {
      const code = `
export function createUser() {
  function generateId() {
    return Math.random().toString(36).substring(2, 15)
  }
  return { id: generateId() }
}
      `.trim()
      const findings = detectDangerousFunctions(code, '/lib/users.ts')

      // generateId should be detected and skipped (UUID-like)
      expect(findings).toHaveLength(0)
    })
  })

  describe('Regression: Ensure Security Cases Still Detected', () => {
    it('should still detect token generation in non-auth files', () => {
      const code = `const token = Math.random().toString(36)`
      const findings = detectDangerousFunctions(code, '/routes/api.ts')

      expect(findings).toHaveLength(1)
      expect(findings[0].severity).toBe('high')
    })

    it('should still detect secret generation anywhere', () => {
      const code = `const secret = Math.random()`
      const findings = detectDangerousFunctions(code, '/utils/helpers.ts')

      expect(findings).toHaveLength(1)
      expect(findings[0].severity).toBe('high')
    })

    it('should still flag long random strings without truncation', () => {
      const code = `const longToken = Math.random().toString(36)`
      const findings = detectDangerousFunctions(code, '/lib/api.ts')

      expect(findings).toHaveLength(1)
      // Should not be downgraded to info
      expect(findings[0].severity).not.toBe('info')
    })
  })
})
