// @vitest-environment jsdom
//
// The <ReadingProgress> island — a scroll-driven progress bar. We mock
// `@voltro/web`'s `island()` to the identity so the default export IS the raw
// component, then assert it renders the progress-bar element and recomputes its
// width on scroll.

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

vi.mock('@voltro/web', () => ({
  island: (Component: ComponentType<unknown>) => Component,
}))

const { default: ReadingProgress } = await import('./ReadingProgress.island')

;(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('ReadingProgress island', () => {
  test('renders the progress-bar element, hidden from assistive tech', () => {
    render(createElement(ReadingProgress))
    const bar = container.querySelector('.reading-progress') as HTMLElement
    expect(bar).not.toBeNull()
    expect(bar.getAttribute('aria-hidden')).toBe('true')
  })

  test('starts at 0% when the document is not scrollable', () => {
    render(createElement(ReadingProgress))
    const bar = container.querySelector('.reading-progress') as HTMLElement
    // jsdom reports scrollHeight === clientHeight (0), so max <= 0 → 0%.
    expect(bar.style.width).toBe('0%')
  })

  test('recomputes width to 100% at the bottom of a scrollable document', () => {
    render(createElement(ReadingProgress))
    const el = document.documentElement
    Object.defineProperty(el, 'scrollHeight', { value: 2000, configurable: true })
    Object.defineProperty(el, 'clientHeight', { value: 1000, configurable: true })
    Object.defineProperty(el, 'scrollTop', { value: 1000, configurable: true })
    act(() => {
      window.dispatchEvent(new Event('scroll'))
    })
    const bar = container.querySelector('.reading-progress') as HTMLElement
    expect(bar.style.width).toBe('100%')
  })
})
