// @vitest-environment jsdom
//
// `/` changelog index — lists every release, newest first. The real release
// source (`../lib/releases`) reads .mdx via `import.meta.glob` + node-gated
// shiki, so we mock it with canned releases and assert the observable render:
// config exports, meta, one entry per release, and its tags + link.

import { afterEach, describe, expect, test, vi } from 'vitest'
import { act, createElement, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'

interface Release {
  version: string
  releasedAt: string
  slug: string
  tags: ReadonlyArray<string>
  title: string
  summary: string
  html: string
}

const releases: ReadonlyArray<Release> = [
  {
    version: '0.2.0',
    releasedAt: '2026-06-21',
    slug: 'v0-2-0',
    tags: ['feature', 'performance'],
    title: 'Typed env + faster boot',
    summary: 'Declare your environment once.',
    html: '<p>body</p>',
  },
  {
    version: '0.1.0',
    releasedAt: '2026-01-15',
    slug: 'v0-1-0',
    tags: ['feature'],
    title: 'First release',
    summary: 'The initial cut.',
    html: '<p>body</p>',
  },
]

vi.mock('../lib/releases', () => ({ releases }))
// `withLocalePrefix` (lib/locale) reads useLocation; the page pins the locale
// via useLocale, so any bare path is fine here.
vi.mock('@voltro/web', () => ({ useLocation: () => '/' }))
// Chrome (meta via getCatalog + the empty state) comes from @voltro/i18n;
// stub it (identity catalog defs, useLocale → en, <T> passes children through).
vi.mock('@voltro/i18n', () => ({
  defineCatalog: <T,>(c: T): T => c,
  defineLocale:
    () =>
    <T,>(c: T): T =>
      c,
  useLocale: () => 'en',
  useT: (id: string) => id,
  T: ({ id }: { id: string }) => id,
}))

const { default: ChangelogIndex, meta, renderMode, interactive } = await import('./page')

;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true

let container: HTMLDivElement
let root: Root

const render = (node: ReactNode): void => {
  container = document.createElement('div')
  document.body.appendChild(container)
  act(() => {
    root = createRoot(container)
    root.render(node)
  })
}

afterEach(() => {
  if (root) act(() => root.unmount())
  container?.remove()
  document.body.innerHTML = ''
})

describe('changelog index — config + localized meta', () => {
  test('is a static page with zero client JS', () => {
    expect(renderMode).toBe('static')
    expect(interactive).toBe('none')
  })

  test('meta() returns a localized title + description per locale', () => {
    expect(meta({ locale: 'en' }).title).toContain('Changelog')
    expect(meta({ locale: 'en' }).description).toContain('release notes')
    expect(meta({ locale: 'de' }).description).toContain('Release-Notes')
  })
})

describe('changelog index — render', () => {
  test('renders one entry per release, each linking to /<slug> with its tags', () => {
    render(createElement(ChangelogIndex))
    const entries = Array.from(container.querySelectorAll('.changelog-entry'))
    expect(entries).toHaveLength(2)

    const links = Array.from(container.querySelectorAll('.changelog-entry h2 a'))
    expect(links.map((a) => a.getAttribute('href'))).toEqual(['/v0-2-0', '/v0-1-0'])
    expect(links[0]!.textContent).toBe('Typed env + faster boot')

    // The first entry surfaces both of its tags.
    const firstTags = Array.from(entries[0]!.querySelectorAll('.changelog-tag')).map(
      (t) => t.textContent,
    )
    expect(firstTags).toEqual(['feature', 'performance'])
    expect(container.textContent).toContain('v0.2.0')
  })
})
