import { useEffect, useId, useRef, useState } from 'react'
import { LayoutGrid } from 'lucide-react'
import { STAGE_LAYOUT_MODE_OPTIONS, type StageLayoutMode } from '@/lib/stageLayoutMode'

export interface StageViewProps {
  layoutMode: StageLayoutMode
  onLayoutModeChange: (mode: StageLayoutMode) => void
  /** Карусель остальных участников скрыта — на сцене только основная область. */
  hideOthers: boolean
  onHideOthersChange: (hide: boolean) => void
}

/**
 * Блок выбора вида сцены: режим показа (три варианта) + скрытие остальных
 * участников. Один и тот же блок рендерится в двух местах — в поповере кнопки
 * «Вид» на десктопе (`StageViewMenu` ниже) и секцией внутри мобильной шторки
 * настроек (`DeviceSettingsDialog`), поэтому вынесен отдельно.
 *
 * «Скрыть остальных» в режиме «Плитки» заблокировано, а не спрятано: все
 * плитки там равноправны, скрывать нечего, но исчезающий на ровном месте
 * переключатель читался бы как баг — вместо этого он выключен с пояснением.
 */
export function StageViewOptions({
  layoutMode,
  onLayoutModeChange,
  hideOthers,
  onHideOthersChange,
}: StageViewProps) {
  // Радиогруппе нужно имя, уникальное на документ: блок может оказаться на
  // странице дважды (десктопный поповер и шторка живут в разных ветках
  // рендера, но полагаться на это не стоит).
  const groupName = useId()
  const hideOthersDisabled = layoutMode === 'tiles'

  return (
    <div className="stage-view-options">
      <fieldset className="stage-view-modes">
        <legend>Режим показа</legend>
        {STAGE_LAYOUT_MODE_OPTIONS.map((option) => (
          <label
            key={option.mode}
            className={`stage-view-mode${layoutMode === option.mode ? ' is-active' : ''}`}
          >
            <input
              type="radio"
              name={groupName}
              value={option.mode}
              checked={layoutMode === option.mode}
              onChange={() => onLayoutModeChange(option.mode)}
            />
            <span className="stage-view-mode-text">
              <span className="stage-view-mode-title">{option.title}</span>
              <span className="stage-view-mode-hint">{option.hint}</span>
            </span>
          </label>
        ))}
      </fieldset>

      <label className={`stage-view-toggle${hideOthersDisabled ? ' is-disabled' : ''}`}>
        <input
          type="checkbox"
          checked={hideOthers}
          disabled={hideOthersDisabled}
          onChange={(e) => onHideOthersChange(e.target.checked)}
        />
        <span>Скрыть остальных участников</span>
      </label>
      {hideOthersDisabled && (
        <p className="stage-view-note">В режиме «Плитки» все участники равноправны — скрывать нечего.</p>
      )}
    </div>
  )
}

/**
 * Кнопка «Вид» в тулбаре с поповером над ней — десктопный вход в
 * `StageViewOptions`. На мобильном не рендерится вовсе (см. `RoomToolbar`):
 * там тулбар и так ужат до пяти кнопок, а те же настройки доступны секцией
 * «Вид» в шторке настроек.
 *
 * Закрытие по клику вне и Escape — тем же паттерном, что меню пользователя в
 * `ShellTopbar` (слушатели на document, пока меню открыто).
 */
export function StageViewMenu(props: StageViewProps) {
  const [open, setOpen] = useState(false)
  const wrapRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!open) return

    function handlePointerDown(event: MouseEvent) {
      if (wrapRef.current && !wrapRef.current.contains(event.target as Node)) {
        setOpen(false)
      }
    }
    function handleKeydown(event: KeyboardEvent) {
      if (event.key === 'Escape') setOpen(false)
    }

    document.addEventListener('mousedown', handlePointerDown)
    document.addEventListener('keydown', handleKeydown)
    return () => {
      document.removeEventListener('mousedown', handlePointerDown)
      document.removeEventListener('keydown', handleKeydown)
    }
  }, [open])

  return (
    <div className="tb-menu-wrap" ref={wrapRef}>
      <button
        type="button"
        className={`tb-btn${open ? ' is-panel-open' : ''}`}
        aria-label="Вид сцены"
        aria-expanded={open}
        aria-haspopup="dialog"
        onClick={() => setOpen((v) => !v)}
      >
        <span className="icon-shell">
          <LayoutGrid className="lucide" aria-hidden="true" />
        </span>
        <span className="label">Вид</span>
      </button>
      {open && (
        <div className="tb-menu" role="dialog" aria-label="Вид сцены">
          <StageViewOptions {...props} />
        </div>
      )}
    </div>
  )
}
