import { renderToStaticMarkup } from 'react-dom/server'
import { describe, expect, it, vi } from 'vitest'
import type { SecurityAuditRecord } from './types'
import { SecurityAuditSection } from './security-audit-section'

vi.mock('react-i18next', async () => {
  const actual = await vi.importActual<typeof import('react-i18next')>('react-i18next')
  return {
    ...actual,
    useTranslation: () => ({
      t: (key: string, values?: Record<string, unknown>) =>
        values?.count !== undefined ? `${key}:${values.count}` : key,
      i18n: { language: 'en' },
    }),
  }
})

function createAudit(overrides: Partial<SecurityAuditRecord> = {}): SecurityAuditRecord {
  return {
    id: 1,
    scanId: 'scan-abc',
    scannerType: 'semgrep',
    verdict: 'SAFE',
    isSafe: true,
    maxSeverity: null,
    findingsCount: 0,
    findings: [],
    scanDurationSeconds: null,
    scannedAt: '2026-03-20T10:00:00Z',
    createdAt: '2026-03-20T10:00:00Z',
    ...overrides,
  }
}

let mockAudits: SecurityAuditRecord[] | undefined = undefined
let mockIsLoading = false

vi.mock('./use-security-audit', () => ({
  useSecurityAudits: () => ({ data: mockAudits, isLoading: mockIsLoading }),
}))

describe('SecurityAuditSection', () => {
  it('returns null when loading', () => {
    mockAudits = undefined
    mockIsLoading = true

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toBe('')
  })

  it('returns null when audits is undefined', () => {
    mockAudits = undefined
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toBe('')
  })

  it('returns null when audits is an empty array', () => {
    mockAudits = []
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toBe('')
  })

  it('renders the section title when audits are present', () => {
    mockAudits = [createAudit()]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.title')
  })

  it('renders the scanner type for each audit', () => {
    mockAudits = [
      createAudit({ id: 1, scannerType: 'semgrep' }),
      createAudit({ id: 2, scannerType: 'trivy' }),
    ]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('semgrep')
    expect(html).toContain('trivy')
  })

  it('renders the verdict badge for each audit', () => {
    mockAudits = [createAudit({ verdict: 'SUSPICIOUS' })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.verdict.SUSPICIOUS')
  })

  it('renders scanning status when the audit has not completed yet', () => {
    mockAudits = [createAudit({ verdict: 'SUSPICIOUS', scannedAt: null })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} versionStatus="SCANNING" />)

    expect(html).toContain('securityAudit.statusScanning')
    expect(html).not.toContain('securityAudit.verdict.SUSPICIOUS')
  })

  it('renders scan failed status when version scan failed before audit completion', () => {
    mockAudits = [createAudit({ verdict: 'SUSPICIOUS', scannedAt: null })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} versionStatus="SCAN_FAILED" />)

    expect(html).toContain('securityAudit.statusScanFailed')
    expect(html).not.toContain('securityAudit.statusScanning')
  })

  it('renders the findings count', () => {
    mockAudits = [createAudit({ findingsCount: 3 })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.findingsCount:3')
  })

  it('renders the scan duration when available', () => {
    mockAudits = [createAudit({ scanDurationSeconds: 12 })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.scanDuration')
  })

  it('omits the scan duration when null', () => {
    mockAudits = [createAudit({ scanDurationSeconds: null })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).not.toContain('securityAudit.scanDuration')
  })

  it('wraps content in a Card when bare is not set', () => {
    mockAudits = [createAudit()]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    // The Card renders with p-8 class
    expect(html).toContain('p-8')
  })

  it('renders a plain div wrapper when bare is true', () => {
    mockAudits = [createAudit()]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} bare />)

    // bare mode should not include p-8 (from Card)
    expect(html).not.toContain('p-8')
    expect(html).toContain('securityAudit.title')
  })

  it('renders a findings toggle button when findings exist', () => {
    mockAudits = [
      createAudit({
        findingsCount: 1,
        findings: [
          {
            ruleId: 'SEC-001',
            severity: 'HIGH',
            category: 'injection',
            title: 'Test finding',
            message: null,
            filePath: null,
            lineNumber: null,
            codeSnippet: null,
            remediation: null,
            analyzer: null,
            metadata: {},
          },
        ],
      }),
    ]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.findings')
  })

  it('does not render a findings toggle button when findings array is empty', () => {
    mockAudits = [createAudit({ findings: [], findingsCount: 0 })]
    mockIsLoading = false

    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    // The "Findings" toggle button label should not appear
    // (only the findingsCount text appears)
    expect(html).toContain('securityAudit.findingsCount')
  })

  it('sorts findings by severity when rendering (CRITICAL before INFO)', () => {
    mockAudits = [
      createAudit({
        findingsCount: 3,
        findings: [
          {
            ruleId: 'LOW-1',
            severity: 'LOW',
            category: 'misc',
            title: 'Low finding',
            message: null,
            filePath: null,
            lineNumber: null,
            codeSnippet: null,
            remediation: null,
            analyzer: null,
            metadata: {},
          },
          {
            ruleId: 'CRIT-1',
            severity: 'CRITICAL',
            category: 'injection',
            title: 'Critical finding',
            message: null,
            filePath: null,
            lineNumber: null,
            codeSnippet: null,
            remediation: null,
            analyzer: null,
            metadata: {},
          },
          {
            ruleId: 'INFO-1',
            severity: 'INFO',
            category: 'info',
            title: 'Info finding',
            message: null,
            filePath: null,
            lineNumber: null,
            codeSnippet: null,
            remediation: null,
            analyzer: null,
            metadata: {},
          },
        ],
      }),
    ]
    mockIsLoading = false

    // The component renders findings in sorted order, but they are hidden
    // behind a toggle (expanded state defaults to false in static render).
    // We verify the toggle button is present which means sortFindings ran.
    const html = renderToStaticMarkup(<SecurityAuditSection skillId={1} versionId={10} />)

    expect(html).toContain('securityAudit.findings')
  })
})
