// @vitest-environment happy-dom
import { afterEach, describe, expect, it, vi } from 'vitest'
import { fireEvent, render, screen } from '@testing-library/react'
import {
  InspectorExpandButton,
  ResizableAside,
  SECTION_INSPECTOR_DEFAULT_WIDTH,
  SECTION_INSPECTOR_MIN_WIDTH,
  SECTION_INSPECTOR_WIDTH_KEY,
  computeInspectorMaxWidth,
  computeInspectorOverlayWidth,
  readSectionInspectorWidth,
} from '../../components/ui/ResizableAside.js'

const storage = new Map<string, string>()
vi.stubGlobal('localStorage', {
  getItem: (key: string) => storage.get(key) ?? null,
  setItem: (key: string, value: string) => void storage.set(key, String(value)),
  removeItem: (key: string) => void storage.delete(key),
  clear: () => storage.clear(),
})

vi.stubGlobal(
  'ResizeObserver',
  class {
    constructor(private callback: ResizeObserverCallback) {}
    observe(target: Element) {
      const width =
        target instanceof HTMLElement
          ? Number.parseFloat(target.style.width) || target.clientWidth || 900
          : 900
      this.callback([{ contentRect: { width, height: 600 } } as ResizeObserverEntry], this)
    }
    unobserve() {}
    disconnect() {}
  },
)

afterEach(() => {
  storage.clear()
})

describe('inspector width helpers', () => {
  it('caps inline max width to the container minus a canvas peek', () => {
    expect(computeInspectorMaxWidth(1200)).toBe(640)
    expect(computeInspectorMaxWidth(500)).toBe(404)
    expect(computeInspectorMaxWidth(200)).toBe(SECTION_INSPECTOR_MIN_WIDTH)
  })

  it('computes overlay width for narrow editor rows', () => {
    expect(computeInspectorOverlayWidth(375)).toBe(343)
    expect(computeInspectorOverlayWidth(768)).toBe(480)
  })
})

describe('ResizableAside', () => {
  it('renders a vertical resize separator with keyboard support', () => {
    render(
      <div style={{ width: 900 }}>
        <ResizableAside aria-label="Section editor">
          <p>Inspector content</p>
        </ResizableAside>
      </div>,
    )

    expect(screen.getByText('Inspector content')).toBeTruthy()
    const separator = screen.getByRole('separator', { name: 'Resize inspector panel' })
    expect(separator.getAttribute('aria-orientation')).toBe('vertical')
    expect(separator.getAttribute('aria-valuemin')).toBe(String(SECTION_INSPECTOR_MIN_WIDTH))
  })

  it('widens when dragging the separator left', () => {
    render(
      <div style={{ width: 900 }}>
        <ResizableAside aria-label="Section editor">
          <p>Inspector content</p>
        </ResizableAside>
      </div>,
    )

    const aside = screen.getByLabelText('Section editor')
    const separator = screen.getByRole('separator', { name: 'Resize inspector panel' })

    expect(aside.style.width).toBe(`${SECTION_INSPECTOR_DEFAULT_WIDTH}px`)

    fireEvent.pointerDown(separator, { clientX: 900, button: 0, pointerId: 1 })
    fireEvent.pointerMove(separator, { clientX: 860, pointerId: 1 })
    expect(aside.style.width).toBe(`${SECTION_INSPECTOR_DEFAULT_WIDTH + 40}px`)

    fireEvent.pointerUp(separator, { pointerId: 1 })
    expect(localStorage.getItem(SECTION_INSPECTOR_WIDTH_KEY)).toBe(
      String(SECTION_INSPECTOR_DEFAULT_WIDTH + 40),
    )
  })

  it('nudges width with arrow keys and persists', () => {
    render(
      <div style={{ width: 900 }}>
        <ResizableAside aria-label="Section editor">
          <p>Inspector content</p>
        </ResizableAside>
      </div>,
    )

    const aside = screen.getByLabelText('Section editor')
    const separator = screen.getByRole('separator', { name: 'Resize inspector panel' })

    separator.focus()
    fireEvent.keyDown(separator, { key: 'ArrowLeft' })
    expect(aside.style.width).toBe(`${SECTION_INSPECTOR_DEFAULT_WIDTH + 16}px`)
    expect(readSectionInspectorWidth()).toBe(SECTION_INSPECTOR_DEFAULT_WIDTH + 16)
  })

  it('expands to overlay width on narrow containers', () => {
    render(
      <div style={{ width: 375 }}>
        <ResizableAside aria-label="Section editor">
          <InspectorExpandButton />
          <p>Inspector content</p>
        </ResizableAside>
      </div>,
    )

    const aside = screen.getByLabelText('Section editor')
    fireEvent.click(screen.getByRole('button', { name: 'Expand inspector panel' }))

    expect(aside.getAttribute('data-overlay')).toBe('')
    expect(aside.style.width).toBe(`${computeInspectorOverlayWidth(375)}px`)
  })
})
