/**
 * Inline Suppression Parser Tests
 */

import {
  parseInlineSuppressions,
  isLineSuppressed,
  extractSuppressionReasons,
  generateSuppressionComment,
} from '../inline-parser'

describe('Inline Suppression Parser', () => {
  describe('parseInlineSuppressions', () => {
    it('should parse next-line suppression comments', () => {
      const content = `
const x = 1;
// oculum-ignore-next-line: false positive
const secret = "abc123";
const y = 2;
`
      const suppressions = parseInlineSuppressions(content)

      // Line 4 (const secret) should be suppressed by line 3's comment
      expect(suppressions.has(4)).toBe(true)
      expect(suppressions.get(4)?.reason).toBe('false positive')
      expect(suppressions.get(4)?.type).toBe('next-line')
    })

    it('should parse same-line suppression comments', () => {
      const content = `
const x = 1;
const secret = "abc123"; // oculum-ignore: known safe
const y = 2;
`
      const suppressions = parseInlineSuppressions(content)

      // Line 3 should be suppressed
      expect(suppressions.has(3)).toBe(true)
      expect(suppressions.get(3)?.reason).toBe('known safe')
      expect(suppressions.get(3)?.type).toBe('same-line')
    })

    it('should parse block suppressions', () => {
      const content = `
const x = 1;
/* oculum-ignore-block: legacy code */
const secret1 = "abc";
const secret2 = "def";
/* oculum-ignore-block-end */
const y = 2;
`
      const suppressions = parseInlineSuppressions(content)

      // Lines 4 and 5 should be suppressed by the block
      expect(suppressions.has(4)).toBe(true)
      expect(suppressions.has(5)).toBe(true)
      expect(suppressions.get(4)?.reason).toBe('legacy code')
      expect(suppressions.get(5)?.reason).toBe('legacy code')

      // Lines before and after block should not be suppressed
      expect(suppressions.has(2)).toBe(false)
      expect(suppressions.has(7)).toBe(false)
    })

    it('should parse rule-specific suppressions', () => {
      const content = `
// oculum-ignore-next-line [hardcoded_secret]: test data
const secret = "test123";
`
      const suppressions = parseInlineSuppressions(content)

      expect(suppressions.has(3)).toBe(true)
      expect(suppressions.get(3)?.ruleId).toBe('hardcoded_secret')
      expect(suppressions.get(3)?.reason).toBe('test data')
    })

    it('should support Python-style comments (#)', () => {
      const content = `
x = 1
# oculum-ignore-next-line: test data
secret = "abc123"
`
      const suppressions = parseInlineSuppressions(content)

      expect(suppressions.has(4)).toBe(true)
      expect(suppressions.get(4)?.reason).toBe('test data')
    })

    it('should support SQL-style comments (--)', () => {
      const content = `
SELECT 1;
-- oculum-ignore-next-line: intentional
SELECT password FROM users;
`
      const suppressions = parseInlineSuppressions(content)

      expect(suppressions.has(4)).toBe(true)
      expect(suppressions.get(4)?.reason).toBe('intentional')
    })

    it('should handle empty files', () => {
      const suppressions = parseInlineSuppressions('')
      expect(suppressions.size).toBe(0)
    })

    it('should not match partial oculum-ignore patterns', () => {
      const content = `
// This is not oculum-ignore but mentions it
const x = "oculum-ignore";
`
      const suppressions = parseInlineSuppressions(content)
      expect(suppressions.size).toBe(0)
    })
  })

  describe('isLineSuppressed', () => {
    it('should return suppression for suppressed line', () => {
      const content = `
// oculum-ignore-next-line: reason
const x = 1;
`
      const suppressions = parseInlineSuppressions(content)
      const result = isLineSuppressed(suppressions, 3)

      expect(result).not.toBeNull()
      expect(result?.reason).toBe('reason')
    })

    it('should return null for non-suppressed line', () => {
      const content = `
// oculum-ignore-next-line: reason
const x = 1;
const y = 2;
`
      const suppressions = parseInlineSuppressions(content)
      const result = isLineSuppressed(suppressions, 4)

      expect(result).toBeNull()
    })

    it('should respect rule-specific suppressions', () => {
      const content = `
// oculum-ignore-next-line [hardcoded_secret]: reason
const x = 1;
`
      const suppressions = parseInlineSuppressions(content)

      // Should match hardcoded_secret
      expect(isLineSuppressed(suppressions, 3, 'hardcoded_secret')).not.toBeNull()

      // Should not match other categories
      expect(isLineSuppressed(suppressions, 3, 'high_entropy_string')).toBeNull()

      // Should match if no category specified
      expect(isLineSuppressed(suppressions, 3)).not.toBeNull()
    })
  })

  describe('extractSuppressionReasons', () => {
    it('should extract all unique suppression reasons', () => {
      const content = `
// oculum-ignore-next-line: reason 1
const a = 1;
// oculum-ignore-next-line: reason 2
const b = 2;
`
      const reasons = extractSuppressionReasons(content)

      expect(reasons).toHaveLength(2)
      expect(reasons.map(r => r.reason)).toContain('reason 1')
      expect(reasons.map(r => r.reason)).toContain('reason 2')
    })

    it('should not duplicate block suppression reasons', () => {
      const content = `
/* oculum-ignore-block: block reason */
const a = 1;
const b = 2;
/* oculum-ignore-block-end */
`
      const reasons = extractSuppressionReasons(content)

      // Should only have one entry for the block, not one per line
      expect(reasons).toHaveLength(1)
      expect(reasons[0].reason).toBe('block reason')
    })
  })

  describe('generateSuppressionComment', () => {
    it('should generate next-line comment', () => {
      const comment = generateSuppressionComment('false positive')
      expect(comment).toBe('// oculum-ignore-next-line: false positive')
    })

    it('should generate same-line comment', () => {
      const comment = generateSuppressionComment('known safe', { type: 'same-line' })
      expect(comment).toBe('// oculum-ignore: known safe')
    })

    it('should generate comment with rule ID', () => {
      const comment = generateSuppressionComment('test data', { ruleId: 'hardcoded_secret' })
      expect(comment).toBe('// oculum-ignore-next-line [hardcoded_secret]: test data')
    })

    it('should support different comment styles', () => {
      expect(generateSuppressionComment('reason', { commentStyle: '#' }))
        .toBe('# oculum-ignore-next-line: reason')
      expect(generateSuppressionComment('reason', { commentStyle: '--' }))
        .toBe('-- oculum-ignore-next-line: reason')
    })
  })
})
