import { useEffect, useRef } from 'react'
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { fireEvent, render, screen } from '@testing-library/react'
import { Provider } from '../../provider/widget-provider'
import { clearAllWidgetStores, getWidgetStore } from '../../stores'
import { FullScreen } from './fullscreen'
import type { FullScreenWidgetState } from './types'

beforeEach(() => clearAllWidgetStores())
afterEach(() => clearAllWidgetStores())

describe('<FullScreen.Trigger> — store toggle', () => {
  it('does not surface isFullScreen on the base WidgetState until the trigger fires', () => {
    render(
      <Provider id='fs1' data={[]}>
        <FullScreen.Trigger />
      </Provider>,
    )
    const state = getWidgetStore('fs1').getState()
    expect((state as FullScreenWidgetState).isFullScreen).toBeUndefined()
  })

  it('toggles state on click and swaps the trigger label', () => {
    render(
      <Provider id='fs2' data={[]}>
        <FullScreen.Trigger labels={{ open: 'Expand', close: 'Shrink' }} />
      </Provider>,
    )
    fireEvent.click(screen.getByLabelText('Expand'))
    expect(screen.getByLabelText('Shrink')).toBeTruthy()
    expect(
      (getWidgetStore('fs2').getState() as FullScreenWidgetState).isFullScreen,
    ).toBe(true)
    fireEvent.click(screen.getByLabelText('Shrink'))
    expect(screen.getByLabelText('Expand')).toBeTruthy()
    expect(
      (getWidgetStore('fs2').getState() as FullScreenWidgetState).isFullScreen,
    ).toBe(false)
  })

  it('keepAlive remount restores isFullScreen', () => {
    const { unmount } = render(
      <Provider id='fs3' data={[]} keepAlive>
        <FullScreen.Trigger labels={{ open: 'Maximise' }} />
      </Provider>,
    )
    fireEvent.click(screen.getByLabelText('Maximise'))
    expect(
      (getWidgetStore('fs3').getState() as FullScreenWidgetState).isFullScreen,
    ).toBe(true)
    unmount()
    render(
      <Provider id='fs3' data={[]} keepAlive>
        <FullScreen.Trigger labels={{ open: 'Maximise' }} />
      </Provider>,
    )
    expect(
      (getWidgetStore('fs3').getState() as FullScreenWidgetState).isFullScreen,
    ).toBe(true)
  })
})

describe('<FullScreen.Slot> — render-prop body + portal', () => {
  it('passes the live isFullScreen flag to the render prop', () => {
    let received: boolean | undefined
    render(
      <Provider id='fs-rp' data={[]}>
        <FullScreen.Trigger />
        <FullScreen.Slot>
          {(isFullScreen) => {
            received = isFullScreen
            return <span data-testid='body'>body</span>
          }}
        </FullScreen.Slot>
      </Provider>,
    )
    expect(received).toBe(false)
    fireEvent.click(screen.getByLabelText('Open in full screen'))
    expect(received).toBe(true)
  })

  it('renders the title above the body when open', async () => {
    render(
      <Provider id='fs-title' data={[]}>
        <FullScreen.Trigger />
        <FullScreen.Slot title='Sales by region'>
          {() => <div>body</div>}
        </FullScreen.Slot>
      </Provider>,
    )
    fireEvent.click(screen.getByLabelText('Open in full screen'))
    expect(await screen.findByText('Sales by region')).toBeTruthy()
  })

  it('still renders the close button when no title is given', async () => {
    render(
      <Provider id='fs-no-title' data={[]}>
        <FullScreen.Trigger />
        <FullScreen.Slot>{() => <div>body</div>}</FullScreen.Slot>
      </Provider>,
    )
    fireEvent.click(screen.getByLabelText('Open in full screen'))
    const closes = await screen.findAllByLabelText('Exit full screen')
    expect(closes.length).toBeGreaterThan(0)
  })

  it('keeps the same DOM node across the fullscreen toggle (portal reparent)', () => {
    render(
      <Provider id='fs-reparent' data={[]}>
        <FullScreen.Trigger />
        <FullScreen.Slot title='X'>
          {() => <span data-testid='inner'>inner</span>}
        </FullScreen.Slot>
      </Provider>,
    )
    const before = screen.getByTestId('inner')
    fireEvent.click(screen.getByLabelText('Open in full screen'))
    const after = screen.getByTestId('inner')
    expect(after).toBe(before)
  })

  it('mounts the body exactly once across multiple fullscreen toggles', () => {
    let mountCount = 0
    function CountingChild() {
      const counted = useRef(false)
      useEffect(() => {
        if (counted.current) return
        counted.current = true
        mountCount += 1
      }, [])
      return <div data-testid='counter'>x</div>
    }
    // Distinct labels for the trigger so its "close" aria-label can't collide
    // with the modal's own close button (also "Exit full screen" by default
    // when keepMounted=true keeps the modal in DOM).
    render(
      <Provider id='fs-mount-once' data={[]}>
        <FullScreen.Trigger labels={{ open: 'OpenT', close: 'CloseT' }} />
        <FullScreen.Slot title='Z'>{() => <CountingChild />}</FullScreen.Slot>
      </Provider>,
    )
    expect(mountCount).toBe(1)
    fireEvent.click(screen.getByLabelText('OpenT'))
    expect(mountCount).toBe(1)
    fireEvent.click(screen.getByLabelText('CloseT'))
    expect(mountCount).toBe(1)
    fireEvent.click(screen.getByLabelText('OpenT'))
    expect(mountCount).toBe(1)
  })
})
