/**
 * PaneToggleStrip — the persistent show/hide strip (spec §01A).
 *
 * Per the interaction contract (docs/architecture/10 → "Resolved — pane toggle
 * strip", consulted via /council → WAI-ARIA APG `toolbar` + `button`):
 *
 * - It is an APG **toolbar** (`role="toolbar"`, vertical) — a **single tab stop**
 *   with a **roving tabindex**, so the whole strip is one stop in the tab order
 *   and Up/Down (Left/Right duplicate) move among its controls; Home/End jump to
 *   the ends. Re-entry restores the last-focused control (the `focusIndex` state).
 * - The three pane controls are **toggle buttons** (`aria-pressed`) with a
 *   **stable** accessible name ("Library pane" …) that never changes with state;
 *   `aria-pressed=true` ⇔ pane visible. The positional glyph shows which pane.
 * - The **Datasets** control is a plain command button (no `aria-pressed`) — APG
 *   permits mixed control types in one toolbar — set off by a divider, kept last
 *   in the roving order.
 * - Focus is never orphaned: hiding is only ever initiated *from here*, so the
 *   activating toggle keeps focus (it stays mounted, flips to not-pressed). The
 *   strip is never itself hidden, so it stays reachable even with all panes hidden.
 */

import { useRef, useState } from 'react';
import { openModal } from '../modals/ModalCoordinator';
import { usePanesStore, type PaneName } from '../stores/PanesStore';
import { Icon, type IconName } from './Icon';
import { IconButton } from './IconButton';
import styles from './PaneToggleStrip.module.css';

interface PaneItem {
  pane: PaneName;
  icon: IconName;
  /** Stable accessible name (APG: never changes with the pressed state). */
  label: string;
  /** The id of the pane section this toggle controls. */
  controls: string;
}

const PANES: readonly PaneItem[] = [
  { pane: 'library', icon: 'pane-library', label: 'Library pane', controls: 'pane-library' },
  { pane: 'editor', icon: 'pane-editor', label: 'Editor pane', controls: 'pane-editor' },
  { pane: 'preview', icon: 'pane-preview', label: 'Preview pane', controls: 'pane-preview' },
];

export function PaneToggleStrip() {
  const libraryVisible = usePanesStore((s) => s.libraryVisible);
  const editorVisible = usePanesStore((s) => s.editorVisible);
  const previewVisible = usePanesStore((s) => s.previewVisible);
  const togglePane = usePanesStore((s) => s.togglePane);
  const visible: Record<PaneName, boolean> = {
    library: libraryVisible,
    editor: editorVisible,
    preview: previewVisible,
  };

  // The strip's own element — its parent is the panes row, so we can measure the
  // width available to the panes (row minus this strip) when toggling the editor,
  // which needs it to remember/restore the editor's width (PanesStore.togglePane).
  const stripRef = useRef<HTMLDivElement>(null);
  const panesInner = (): number => {
    const strip = stripRef.current;
    const row = strip?.parentElement;
    return row ? row.clientWidth - strip.offsetWidth : 0;
  };

  // Roving tabindex over the toggles + the trailing Datasets action (the divider
  // is not a control). One tab stop; the focused index is the only `tabIndex=0`.
  const count = PANES.length + 1;
  const datasetsIndex = PANES.length;
  const refs = useRef<Array<HTMLButtonElement | null>>([]);
  const [focusIndex, setFocusIndex] = useState(0);

  const focusAt = (i: number) => {
    const idx = ((i % count) + count) % count;
    setFocusIndex(idx);
    refs.current[idx]?.focus();
  };

  const onKeyDown = (e: React.KeyboardEvent, index: number) => {
    switch (e.key) {
      case 'ArrowDown':
      case 'ArrowRight':
        focusAt(index + 1);
        break;
      case 'ArrowUp':
      case 'ArrowLeft':
        focusAt(index - 1);
        break;
      case 'Home':
        focusAt(0);
        break;
      case 'End':
        focusAt(count - 1);
        break;
      default:
        return; // not ours — let it bubble
    }
    e.preventDefault();
  };

  return (
    <div
      ref={stripRef}
      role="toolbar"
      aria-orientation="vertical"
      aria-label="Workspace panes"
      className={styles.strip}
    >
      {PANES.map((item, i) => (
        <IconButton
          key={item.pane}
          ref={(el) => {
            refs.current[i] = el;
          }}
          aria-pressed={visible[item.pane]}
          label={item.label}
          // Only point at the pane while it's actually mounted: App unmounts a
          // hidden pane's <section>, so emitting aria-controls then would leave a
          // dangling IDREF (invalid, even if AT ignores it). The association is
          // meaningful only when the target exists, and the aria-pressed state
          // already conveys hidden/shown either way (contract: arch/10 → toggle
          // strip — the bullet lists aria-pressed + a stable name, not controls).
          aria-controls={visible[item.pane] ? item.controls : undefined}
          // Description (not the name): hints what activating does. The name stays
          // stable (aria-label) per APG's toggle-button rule.
          title={`${visible[item.pane] ? 'Hide' : 'Show'} ${item.label.toLowerCase()}`}
          tabIndex={focusIndex === i ? 0 : -1}
          className={visible[item.pane] ? styles.pressed : undefined}
          onClick={() => {
            togglePane(item.pane, panesInner());
            setFocusIndex(i);
          }}
          onKeyDown={(e) => onKeyDown(e, i)}
        >
          <Icon name={item.icon} />
        </IconButton>
      ))}

      <div className={styles.divider} aria-hidden="true" />

      <IconButton
        ref={(el) => {
          refs.current[datasetsIndex] = el;
        }}
        label="Datasets"
        aria-keyshortcuts="Meta+K Control+K"
        title="Datasets (⌘/Ctrl+K)"
        tabIndex={focusIndex === datasetsIndex ? 0 : -1}
        onClick={() => {
          openModal('datasets');
          setFocusIndex(datasetsIndex);
        }}
        onKeyDown={(e) => onKeyDown(e, datasetsIndex)}
      >
        <Icon name="dataset" />
      </IconButton>
    </div>
  );
}
