import { describe, it, expect } from 'vitest'
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
import { parseChangelog, versionAnchorId } from '../playground/docs/changelog-parse'

const __dirname = dirname(fileURLToPath(import.meta.url))
const CHANGELOG = readFileSync(resolve(__dirname, '..', 'CHANGELOG.md'), 'utf8')

describe('versionAnchorId', () => {
  it('slugifies a version into a stable dashed anchor', () => {
    expect(versionAnchorId('0.10.1')).toBe('v-0-10-1')
    expect(versionAnchorId('1.0.0')).toBe('v-1-0-0')
  })
})

describe('parseChangelog', () => {
  const fixture = [
    '# Changelog',
    '',
    'Preamble line.',
    '',
    '## 0.2.0',
    '',
    '### Minor Changes',
    '',
    '- did a thing with `<TopBar>` and a fence:',
    '  ```vue',
    '  <TopBar show-menu />',
    '  ```',
    '',
    '## 0.1.0',
    '',
    '### Patch Changes',
    '',
    '- first release',
    '',
  ].join('\n')

  it('captures preamble, every version, kind, and verbatim body', () => {
    const { preamble, entries } = parseChangelog(fixture, '0.2.0')
    expect(preamble).toBe('# Changelog\n\nPreamble line.')
    expect(entries.map((e) => e.version)).toEqual(['0.2.0', '0.1.0'])
    expect(entries[0].kind).toBe('minor')
    expect(entries[1].kind).toBe('patch')
    expect(entries[0].isCurrent).toBe(true)
    expect(entries[1].isCurrent).toBe(false)
    // Body is verbatim — HTML-like tokens + fenced code preserved literally, never dropped.
    expect(entries[0].body).toContain('<TopBar show-menu />')
    expect(entries[0].body).toContain('```vue')
    expect(entries[1].body).toContain('first release')
  })

  it('parses the real CHANGELOG.md: every ## heading becomes an entry with a body', () => {
    const headingCount = (CHANGELOG.match(/^##\s+\d+\.\d+\.\d+/gm) ?? []).length
    const { entries } = parseChangelog(CHANGELOG, '0.10.1')
    expect(headingCount).toBeGreaterThan(0)
    expect(entries.length).toBe(headingCount)
    expect(entries.every((e) => e.body.length > 0)).toBe(true)
    // Anchor ids are unique so the version menu never collides on scroll.
    const ids = entries.map((e) => versionAnchorId(e.version))
    expect(new Set(ids).size).toBe(ids.length)
  })
})
