// a11y-modal.jsx — End-user accessibility customization modal.
// Live-applies settings to the demo page via data attributes & CSS variables.

// ── Icons ────────────────────────────────────────────────────────────────────
const AXIcon = ({ d, size = 20, sw = 1.6, fill = 'none' }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke="currentColor"
    strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    {Array.isArray(d) ? d.map((dd, i) => <path key={i} d={dd} />) : <path d={d} />}
  </svg>
);
const IconAccess = ({ size = 20, sw = 1.8 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
    strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    {/* Three sliders — a "customize / adjust" mark */}
    <line x1="4" y1="6"  x2="20" y2="6"  />
    <line x1="4" y1="12" x2="20" y2="12" />
    <line x1="4" y1="18" x2="20" y2="18" />
    <circle cx="15" cy="6"  r="2.4" fill="currentColor" stroke="none" />
    <circle cx="9"  cy="12" r="2.4" fill="currentColor" stroke="none" />
    <circle cx="16" cy="18" r="2.4" fill="currentColor" stroke="none" />
  </svg>
);
const IconText    = (p) => <AXIcon {...p} d="M4 6V4h16v2M9 20h6M12 4v16" />;
const IconPalette = (p) => <AXIcon {...p} d="M12 21a9 9 0 1 1 9-9c0 2.5-2 4-4 4h-2a2 2 0 0 0-2 2v1a2 2 0 0 1-1 2zM7 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM7 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM11 6a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM16 8a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />;
const IconMotion  = (p) => <AXIcon {...p} d="M12 3l3 4-3 4-3-4 3-4zM3 12l4 3 4-3-4-3-4 3zM21 12l-4-3-4 3 4 3 4-3zM12 21l3-4-3-4-3 4 3 4z" />;
const IconClose   = (p) => <AXIcon {...p} d="M6 6l12 12M18 6L6 18" />;
const IconReset   = (p) => <AXIcon {...p} d="M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5" />;
const IconMinus   = (p) => <AXIcon {...p} d="M5 12h14" />;
const IconPlus    = (p) => <AXIcon {...p} d="M12 5v14M5 12h14" />;
const IconCheck   = (p) => <AXIcon {...p} d="M5 13l4 4 10-10" />;
const IconStar    = (p) => <AXIcon {...p} d="M12 3l3 6 6 1-4.5 4.5L17 21l-5-3-5 3 .5-6.5L3 10l6-1z" />;
const IconBookOpen= (p) => <AXIcon {...p} d="M3 5v14a2 2 0 0 0 2-2h6V3H5a2 2 0 0 0-2 2zM21 5v14a2 2 0 0 1-2-2h-6V3h6a2 2 0 0 1 2 2z" />;
const IconEyeOff  = (p) => <AXIcon {...p} d="M3 3l18 18M10 5a9 9 0 0 1 11 7c-.4 1-1 2-1.8 3M6 7c-1.6 1.3-2.8 3-3 5 1 3 4 7 9 7 2 0 3.7-.6 5-1.5" />;

// ── Defaults & profiles ──────────────────────────────────────────────────────
const A11Y_DEFAULTS = {
  fontScale: 1.0,
  lineHeight: 1.5,
  letterSpacing: 0,
  paragraphSpacing: 'normal', // normal | loose | extra
  fontFamily: 'default',      // default | serif | dyslexic | mono
  theme: 'default',           // default | dark | hc | sepia
  saturation: 100,
  contrast: 100,
  colorBlind: 'none',         // none | protan | deuter | tritan | mono
  highlightLinks: false,
  emphHeadings: false,
  strongFocus: false,
  pauseAnimations: false,
  bigCursor: false,
  readingMask: false,
  hideImages: false,
};

const A11Y_PROFILES = [
  {
    id: 'default',
    name: 'Default',
    desc: "The site's original appearance.",
    icon: IconStar,
    settings: { ...A11Y_DEFAULTS },
  },
  {
    id: 'easier',
    name: 'Easy reading',
    desc: 'Larger text, more space between lines.',
    icon: IconBookOpen,
    settings: {
      ...A11Y_DEFAULTS,
      fontScale: 1.3, lineHeight: 1.8, letterSpacing: 0.02,
      fontFamily: 'dyslexic', paragraphSpacing: 'loose',
      emphHeadings: true, strongFocus: true,
    },
  },
  {
    id: 'contrast',
    name: 'High contrast',
    desc: 'Yellow on black for low vision.',
    icon: IconPalette,
    settings: {
      ...A11Y_DEFAULTS,
      theme: 'hc', fontScale: 1.15, strongFocus: true, highlightLinks: true,
    },
  },
  {
    id: 'colorblind',
    name: 'Color blindness',
    desc: 'Filter for red-green color blindness.',
    icon: IconPalette,
    settings: {
      ...A11Y_DEFAULTS,
      colorBlind: 'deuter', highlightLinks: true,
    },
  },
  {
    id: 'calm',
    name: 'Calm reading',
    desc: 'Sepia tone and paused animations.',
    icon: IconBookOpen,
    settings: {
      ...A11Y_DEFAULTS,
      theme: 'sepia', fontScale: 1.15, lineHeight: 1.7,
      pauseAnimations: true, fontFamily: 'serif',
      paragraphSpacing: 'loose',
    },
  },
];

function isProfileActive(profile, settings) {
  return Object.keys(profile.settings).every(
    k => JSON.stringify(profile.settings[k]) === JSON.stringify(settings[k])
  );
}

// ── Apply settings → DOM ─────────────────────────────────────────────────────
function applySettings(rootEl, s) {
  if (!rootEl) return;
  // CSS variables
  rootEl.style.setProperty('--dp-scale', s.fontScale);
  rootEl.style.setProperty('--dp-lh', s.lineHeight);
  rootEl.style.setProperty('--dp-ls', `${s.letterSpacing}em`);

  // Data attrs
  const attrs = {
    'data-ax-font': s.fontFamily === 'default' ? null : s.fontFamily,
    'data-ax-theme': s.theme === 'default' ? null : s.theme,
    'data-ax-para': s.paragraphSpacing === 'normal' ? null : s.paragraphSpacing,
    'data-ax-links': s.highlightLinks ? 'highlight' : null,
    'data-ax-headings': s.emphHeadings ? 'emph' : null,
    'data-ax-focus': s.strongFocus ? 'strong' : null,
    'data-ax-motion': s.pauseAnimations ? 'paused' : null,
    'data-ax-cursor': s.bigCursor ? 'big' : null,
    'data-ax-images': s.hideImages ? 'off' : null,
  };
  for (const [k, v] of Object.entries(attrs)) {
    if (v == null) rootEl.removeAttribute(k);
    else rootEl.setAttribute(k, v);
  }

  // Filter chain (saturate / contrast / color-blind SVG filter)
  const filters = [];
  if (s.saturation !== 100) filters.push(`saturate(${s.saturation}%)`);
  if (s.contrast !== 100) filters.push(`contrast(${s.contrast}%)`);
  if (s.colorBlind !== 'none') filters.push(`url(#ax-cb-${s.colorBlind})`);
  rootEl.style.filter = filters.join(' ');
}

// ── Form primitives matching design system ───────────────────────────────────
function AXSection({ icon: Icon, title, children }) {
  return (
    <section className="axm-section">
      <header className="axm-section-h">
        {Icon && <Icon size={16} />}
        <span>{title}</span>
      </header>
      <div className="axm-section-body">
        {children}
      </div>
    </section>
  );
}

function AXRow({ label, hint, control, stacked }) {
  return (
    <div className={`axm-row ${stacked ? 'axm-row-stacked' : ''}`}>
      <div className="axm-row-l">
        <span className="axm-label">{label}</span>
        {hint && <span className="axm-hint">{hint}</span>}
      </div>
      <div className="axm-row-r">{control}</div>
    </div>
  );
}

function AXStepper({ value, options, format, onChange }) {
  const idx = options.indexOf(value);
  const has = (di) => idx + di >= 0 && idx + di < options.length;
  const step = (di) => has(di) && onChange(options[idx + di]);
  return (
    <div className="axm-stepper">
      <button className="axm-step-btn" disabled={!has(-1)} onClick={() => step(-1)}
        aria-label="Decrease"><IconMinus size={14} /></button>
      <span className="axm-step-val">{format ? format(value) : value}</span>
      <button className="axm-step-btn" disabled={!has(1)} onClick={() => step(1)}
        aria-label="Increase"><IconPlus size={14} /></button>
    </div>
  );
}

function AXSegmented({ value, options, onChange, columns }) {
  return (
    <div className="axm-seg" style={columns ? { gridTemplateColumns: `repeat(${columns},1fr)` } : null}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)}
          className={`axm-seg-btn ${o.value === value ? 'is-active' : ''}`}
          aria-pressed={o.value === value}>
          {o.swatch && <span className="axm-seg-swatch" style={{ background: o.swatch.bg, color: o.swatch.fg, borderColor: o.swatch.br }}>Aa</span>}
          <span className="axm-seg-label">{o.label}</span>
        </button>
      ))}
    </div>
  );
}

function AXToggle({ checked, onChange, label }) {
  return (
    <button onClick={() => onChange(!checked)} role="switch" aria-checked={checked}
      aria-label={label}
      className={`axm-toggle ${checked ? 'is-on' : ''}`}>
      <span className="axm-toggle-thumb" />
    </button>
  );
}

function AXSlider({ value, min, max, step = 1, onChange, format }) {
  return (
    <div className="axm-slider-wrap">
      <input type="range" min={min} max={max} step={step} value={value}
        onChange={e => onChange(Number(e.target.value))}
        className="axm-slider" />
      <span className="axm-slider-val">{format ? format(value) : value}</span>
    </div>
  );
}

// ── Floating launcher (FAB) ──────────────────────────────────────────────────
function AccessibilityFAB({ open, onClick, position = 'bottom-right', dark = false }) {
  const positionStyle = {
    'bottom-right': { right: 24, bottom: 24 },
    'bottom-left':  { left: 24, bottom: 24 },
    'top-right':    { right: 24, top: 24 },
  }[position];
  return (
    <button
      onClick={onClick}
      aria-label={open ? 'Close accessibility menu' : 'Open accessibility menu'}
      aria-expanded={open}
      className={`axm-fab ${open ? 'is-open' : ''} ${dark ? 'axm-dark' : ''}`}
      style={positionStyle}>
      {open ? <IconClose size={22} /> : <IconAccess size={22} />}
      <span className="axm-fab-label">Adjust site</span>
    </button>
  );
}

// ── Profile chip card ────────────────────────────────────────────────────────
function ProfileCard({ profile, active, onClick }) {
  const Icon = profile.icon;
  return (
    <button onClick={onClick} className={`axm-profile ${active ? 'is-active' : ''}`}>
      <span className="axm-profile-icon"><Icon size={18} /></span>
      <span className="axm-profile-text">
        <span className="axm-profile-name">{profile.name}</span>
        <span className="axm-profile-desc">{profile.desc}</span>
      </span>
      {active && <span className="axm-profile-check"><IconCheck size={14} /></span>}
    </button>
  );
}

// ── The modal itself ─────────────────────────────────────────────────────────
function AccessibilityModal({ open, settings, onChange, onClose, style = 'panel', position = 'bottom-right', dark = false }) {
  const update = (key, val) => onChange({ ...settings, [key]: val });
  const reset = () => onChange({ ...A11Y_DEFAULTS });
  const applyProfile = (p) => onChange({ ...p.settings });

  if (!open) return null;

  const containerClass = `axm-modal axm-style-${style} axm-pos-${position} ${dark ? 'axm-dark' : ''}`;

  return (
    <>
      {style === 'dialog' && <div className="axm-backdrop" onClick={onClose} />}
      <div className={containerClass} role="dialog" aria-labelledby="axm-title">
        {/* Header */}
        <header className="axm-header">
          <div className="axm-header-l">
            <div className="axm-logo"><IconAccess size={18} /></div>
            <div className="axm-header-text">
              <h2 id="axm-title" className="axm-title">Adjust your experience</h2>
              <p className="axm-subtitle">Changes are saved for your next visit.</p>
            </div>
          </div>
          <button className="axm-close" onClick={onClose} aria-label="Close">
            <IconClose size={18} />
          </button>
        </header>

        {/* Body */}
        <div className="axm-body">
          {/* Profiles */}
          <AXSection icon={IconStar} title="Quick profiles">
            <div className="axm-profiles">
              {A11Y_PROFILES.map(p => (
                <ProfileCard key={p.id} profile={p}
                  active={isProfileActive(p, settings)}
                  onClick={() => applyProfile(p)} />
              ))}
            </div>
          </AXSection>

          {/* Text */}
          <AXSection icon={IconText} title="Text & reading">
            <AXRow label="Text size" hint={`${Math.round(settings.fontScale*100)}% of the site's default text`}
              control={
                <AXStepper value={settings.fontScale}
                  options={[0.85, 1.0, 1.15, 1.3, 1.5, 1.75, 2.0]}
                  format={v => `${Math.round(v*100)}%`}
                  onChange={v => update('fontScale', v)} />
              } />
            <AXRow label="Line spacing" control={
              <AXSegmented value={settings.lineHeight}
                options={[
                  { value: 1.2, label: 'Tight' },
                  { value: 1.5, label: 'Normal' },
                  { value: 1.8, label: 'Airy' },
                  { value: 2.2, label: 'Wide' },
                ]} columns={4}
                onChange={v => update('lineHeight', v)} />
            } />
            <AXRow label="Letter spacing" control={
              <AXSegmented value={settings.letterSpacing}
                options={[
                  { value: 0,    label: 'Normal' },
                  { value: 0.04, label: 'Wide' },
                  { value: 0.1,  label: 'Wider' },
                ]} columns={3}
                onChange={v => update('letterSpacing', v)} />
            } />
            <AXRow label="Paragraph spacing" control={
              <AXSegmented value={settings.paragraphSpacing}
                options={[
                  { value: 'normal', label: 'Normal' },
                  { value: 'loose',  label: 'More' },
                  { value: 'extra',  label: 'Extra' },
                ]} columns={3}
                onChange={v => update('paragraphSpacing', v)} />
            } />
            <AXRow label="Font" stacked control={
              <AXSegmented value={settings.fontFamily}
                options={[
                  { value: 'default',  label: 'Default',   swatch: { bg:'#fff', fg:'#1E1E1E', br:'#D9D9D9' } },
                  { value: 'dyslexic', label: 'Easy read', swatch: { bg:'#fff', fg:'#1E1E1E', br:'#D9D9D9' } },
                  { value: 'serif',    label: 'Serif',     swatch: { bg:'#fff', fg:'#1E1E1E', br:'#D9D9D9' } },
                  { value: 'mono',     label: 'Monospace', swatch: { bg:'#fff', fg:'#1E1E1E', br:'#D9D9D9' } },
                ]} columns={4}
                onChange={v => update('fontFamily', v)} />
            } />
            <AXRow label="Emphasize headings" hint="Underlines H1–H4"
              control={<AXToggle checked={settings.emphHeadings} onChange={v => update('emphHeadings', v)} />} />
          </AXSection>

          {/* Color & contrast */}
          <AXSection icon={IconPalette} title="Color & contrast">
            <AXRow label="Theme" stacked control={
              <AXSegmented value={settings.theme}
                options={[
                  { value: 'default', label: 'Light',         swatch: { bg:'#fff',     fg:'#1E1E1E', br:'#D9D9D9' } },
                  { value: 'dark',    label: 'Dark',          swatch: { bg:'#1a1a1a',  fg:'#F1F1F1', br:'#3a3a3a' } },
                  { value: 'hc',      label: 'High contrast', swatch: { bg:'#000', fg:'#FFEE00', br:'#FFEE00' } },
                  { value: 'sepia',   label: 'Sepia',         swatch: { bg:'#f4ecd8',   fg:'#3d2f17', br:'#d4c5a0' } },
                ]} columns={4}
                onChange={v => update('theme', v)} />
            } />
            <AXRow label="Saturation" hint="0% = grayscale"
              control={<AXSlider value={settings.saturation} min={0} max={150} step={10}
                onChange={v => update('saturation', v)}
                format={v => `${v}%`} />} />
            <AXRow label="Contrast" control={
              <AXSlider value={settings.contrast} min={80} max={150} step={5}
                onChange={v => update('contrast', v)}
                format={v => `${v}%`} />} />
            <AXRow label="Color blindness filter" stacked control={
              <AXSegmented value={settings.colorBlind}
                options={[
                  { value: 'none',   label: 'Off' },
                  { value: 'protan', label: 'Protanopia' },
                  { value: 'deuter', label: 'Deuteranopia' },
                  { value: 'tritan', label: 'Tritanopia' },
                  { value: 'mono',   label: 'Monochrome' },
                ]} columns={5}
                onChange={v => update('colorBlind', v)} />
            } />
            <AXRow label="Highlight links" hint="Yellow highlight + underline"
              control={<AXToggle checked={settings.highlightLinks} onChange={v => update('highlightLinks', v)} />} />
          </AXSection>

          {/* Motion & cursor */}
          <AXSection icon={IconMotion} title="Motion & cursor">
            <AXRow label="Pause animations" hint="Disables moving elements and transitions"
              control={<AXToggle checked={settings.pauseAnimations} onChange={v => update('pauseAnimations', v)} />} />
            <AXRow label="Large cursor"
              control={<AXToggle checked={settings.bigCursor} onChange={v => update('bigCursor', v)} />} />
            <AXRow label="Reading mask" hint="Light band around pointer, darker elsewhere"
              control={<AXToggle checked={settings.readingMask} onChange={v => update('readingMask', v)} />} />
            <AXRow label="Strong focus ring" hint="Clearer outline when using keyboard navigation"
              control={<AXToggle checked={settings.strongFocus} onChange={v => update('strongFocus', v)} />} />
            <AXRow label="Hide images" hint="Removes images and decorations"
              control={<AXToggle checked={settings.hideImages} onChange={v => update('hideImages', v)} />} />
          </AXSection>
        </div>

        {/* Footer */}
        <footer className="axm-footer">
          <button className="axm-reset" onClick={reset}>
            <IconReset size={14} /> Reset all
          </button>
          <button className="axm-done" onClick={onClose}>Done</button>
        </footer>
      </div>
    </>
  );
}

// ── Reading mask overlay (mouse-tracking horizontal slit) ────────────────────
function ReadingMask({ active, hostRef }) {
  const [y, setY] = React.useState(null);
  React.useEffect(() => {
    if (!active || !hostRef.current) return;
    const host = hostRef.current;
    const onMove = (e) => {
      const r = host.getBoundingClientRect();
      setY(e.clientY - r.top);
    };
    const onLeave = () => setY(null);
    host.addEventListener('mousemove', onMove);
    host.addEventListener('mouseleave', onLeave);
    return () => {
      host.removeEventListener('mousemove', onMove);
      host.removeEventListener('mouseleave', onLeave);
    };
  }, [active]);
  if (!active || y == null) return null;
  const slit = 100;
  return (
    <div className="axm-reading-mask" aria-hidden="true">
      <div className="axm-mask-band" style={{ height: y - slit/2 }} />
      <div className="axm-mask-clear" style={{ height: slit }} />
      <div className="axm-mask-band axm-mask-grow" />
    </div>
  );
}

Object.assign(window, {
  A11Y_DEFAULTS, A11Y_PROFILES, applySettings, isProfileActive,
  AccessibilityFAB, AccessibilityModal, ReadingMask,
  IconAccess, IconClose, IconReset, IconText, IconPalette, IconMotion,
});
