import { useEffect, useRef } from 'react';
import type { ModelOption, RuntimeSettings, TelemetrySnapshot } from '../../lib/contracts';
import { DEFAULT_MAX_TOKENS } from '../../lib/runtime-defaults';
import type { ThemeMode } from '../theme';

interface SettingsSheetProps {
  open: boolean;
  themeMode: ThemeMode;
  onThemeModeChange: (theme: ThemeMode) => void;
  activeModel: ModelOption;
  telemetry: TelemetrySnapshot;
  settings: RuntimeSettings;
  onSettingsChange: (settings: RuntimeSettings) => void;
  onPersistStorage: () => void;
  onClearStorage: () => void;
  onClearConversation: () => void;
  onClose: () => void;
}

export function SettingsSheet({
  open,
  themeMode,
  onThemeModeChange,
  activeModel,
  telemetry,
  settings,
  onSettingsChange,
  onPersistStorage,
  onClearStorage,
  onClearConversation,
  onClose,
}: SettingsSheetProps) {
  const closeButtonRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    if (!open) return;
    closeButtonRef.current?.focus();
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [open, onClose]);

  if (!open) return null;

  const contextLimit = activeModel.id === 'bonsai-27b'
    ? activeModel.defaultContext
    : activeModel.contextLimit;

  const update = <Key extends keyof RuntimeSettings>(key: Key, value: RuntimeSettings[Key]) => {
    onSettingsChange({ ...settings, [key]: value });
  };

  return (
    <div className="settings-layer" role="presentation" onMouseDown={(event) => {
      if (event.target === event.currentTarget) onClose();
    }}>
      <section className="settings-sheet" role="dialog" aria-modal="true" aria-labelledby="settings-title">
        <header>
          <h2 id="settings-title">Chat settings</h2>
          <button ref={closeButtonRef} className="sheet-close" type="button" onClick={onClose} aria-label="Close settings">×</button>
        </header>

        <label className="setting-group setting-select">
          <div><small>Appearance</small><strong>Follow the system or choose a theme</strong></div>
          <select aria-label="Color theme" value={themeMode} onChange={(event) => onThemeModeChange(event.target.value as ThemeMode)}>
            <option value="system">System</option>
            <option value="light">Light</option>
            <option value="dark">Dark</option>
          </select>
        </label>
        <label className="setting-group setting-select">
          <div><small>Compute backend</small><strong>Auto prefers WebGPU</strong></div>
          <select value={settings.backend} onChange={(event) => update('backend', event.target.value as RuntimeSettings['backend'])}>
            <option value="auto">Auto</option>
            <option value="webgpu">WebGPU</option>
            {activeModel.id !== 'bonsai-27b' && <option value="wasm">CPU · WASM</option>}
          </select>
        </label>
        <div className="setting-group">
          <div><small>Selected model</small><strong>{activeModel.label}</strong></div>
          <span className="setting-locked">{activeModel.footprint}</span>
        </div>

        <label className="range-setting">
          <span><small>Context allocation · applied on load</small><strong>{settings.contextSize.toLocaleString()} tokens</strong></span>
          <input
            type="range"
            min={Math.min(1024, activeModel.defaultContext)}
            max={contextLimit}
            step={16}
            value={settings.contextSize}
            onChange={(event) => update('contextSize', Number(event.target.value))}
          />
          <span className="range-limits"><i>{Math.min(1024, activeModel.defaultContext).toLocaleString()}</i><i>{contextLimit.toLocaleString()}</i></span>
        </label>

        <label className="range-setting">
          <span><small>Temperature</small><strong>{settings.temperature.toFixed(2)}</strong></span>
          <input type="range" min="0" max="2" step="0.05" value={settings.temperature} onChange={(event) => update('temperature', Number(event.target.value))} />
          <span className="range-limits"><i>deterministic</i><i>exploratory</i></span>
        </label>

        <label className="range-setting">
          <span><small>Maximum completion</small><strong>{settings.maxTokens} tokens</strong></span>
          <input type="range" min="64" max={DEFAULT_MAX_TOKENS} step="16" value={settings.maxTokens} onChange={(event) => update('maxTokens', Number(event.target.value))} />
          <span className="range-limits"><i>64</i><i>{DEFAULT_MAX_TOKENS.toLocaleString()}</i></span>
        </label>

        <label className="system-prompt-setting">
          <span><small>System instructions</small><strong>Saved with this chat</strong></span>
          <textarea rows={5} value={settings.systemPrompt} onChange={(event) => update('systemPrompt', event.target.value.slice(0, 8192))} />
        </label>

        <div className="settings-actions">
          <button type="button" onClick={onPersistStorage}>Request persistent storage</button>
          <button type="button" onClick={onClearConversation}>Clear conversation</button>
          <button className="danger-action" type="button" onClick={onClearStorage}>Delete cached models</button>
        </div>

        <div className="settings-note">
          <span className="signal-dot" aria-hidden="true" />
          <p><strong>{telemetry.backend} boundary.</strong> Sampling and tools run in local workers. Changing backend or context reloads the selected model on the next run.</p>
        </div>
      </section>
    </div>
  );
}
