import { h } from 'preact';
import { useState, useMemo, useEffect } from 'preact/hooks';
import InterfaceList from './InterfaceList';
import Canvas from './Canvas';
import { wsClient } from './lib/ws';
import { parseInterface } from './lib/xml';
import { newPlotPanel } from './lib/templates';
import { useAuth, canWrite } from './lib/auth';
import type { Interface } from './lib/types';
import HelpModal from './HelpModal';
import ZoomControl from './ZoomControl';
import ControlLogicEditor from './ControlLogicEditor';
import AuditViewer from './AuditViewer';
import ConfigManager from './ConfigManager';

interface Props {
  onEdit?: (iface?: Interface) => void;
  initialInterface?: Interface | null;
  /** Notifies the parent which interface is currently shown (for edit return). */
  onView?: (iface: Interface | null) => void;
}

/** Format a Date as a datetime-local input value (YYYY-MM-DDTHH:MM) */
function toLocalInput(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

export default function ViewMode({ onEdit, initialInterface, onView }: Props) {
  const [currentInterface, setCurrentInterface] = useState<Interface | null>(initialInterface ?? null);
  const [parseError, setParseError] = useState<string | null>(null);
  const [wsStatus, setWsStatus] = useState('connecting');
  const [showHelp, setShowHelp] = useState(false);
  const [helpSection, setHelpSection] = useState('start');
  const [showTimeNav, setShowTimeNav] = useState(false);
  const [showControlLogic, setShowControlLogic] = useState(false);
  const [showAudit, setShowAudit] = useState(false);
  const [showConfig, setShowConfig] = useState(false);
  const [leftW, setLeftW] = useState(220);
  const [listCollapsed, setListCollapsed] = useState(false);
  const me = useAuth();
  const writable = canWrite(me.level);

  function startResize(e: MouseEvent) {
    e.preventDefault();
    const startX = e.clientX;
    const startW = leftW;
    function onMove(mv: MouseEvent) {
      setLeftW(Math.max(140, startW + mv.clientX - startX));
    }
    function onUp() {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
    }
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
  }

  function openHelp(section = 'start') { setHelpSection(section); setShowHelp(true); }

  // Historical time range — null means live
  const now = useMemo(() => new Date(), []);
  const [startInput, setStartInput] = useState(() => toLocalInput(new Date(now.getTime() - 3600_000)));
  const [endInput, setEndInput]     = useState(() => toLocalInput(now));
  const [timeRange, setTimeRange]   = useState<{ start: string; end: string } | null>(null);

  useEffect(() => {
    const unsub = wsClient.status.subscribe(setWsStatus);
    return unsub;
  }, []);

  // When returning from edit mode, show the edited interface
  useEffect(() => {
    if (initialInterface) setCurrentInterface(initialInterface);
  }, [initialInterface]);

  // Auto-hide the interface-selection pane whenever a panel is opened, and keep
  // the parent informed of what's shown (so closing the editor can return here).
  useEffect(() => {
    if (currentInterface) setListCollapsed(true);
    onView?.(currentInterface);
  }, [currentInterface]);

  function handleLoad(xml: string) {
    try {
      setParseError(null);
      setCurrentInterface(parseInterface(xml));
    } catch (err) {
      setParseError(err instanceof Error ? err.message : 'Failed to parse interface file.');
    }
  }

  async function handleNavigate(interfaceId: string) {
    try {
      const res = await fetch(`/api/v1/interfaces/${encodeURIComponent(interfaceId)}`);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      handleLoad(await res.text());
    } catch (err) {
      setParseError(`Failed to load interface "${interfaceId}": ${err instanceof Error ? err.message : err}`);
    }
  }

  /** Load interface by ID and pass parsed object to onEdit */
  async function handleEditById(id: string) {
    try {
      const res = await fetch(`/api/v1/interfaces/${encodeURIComponent(id)}`);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const iface = parseInterface(await res.text());
      onEdit?.(iface);
    } catch (err) {
      setParseError(`Failed to load interface for editing: ${err instanceof Error ? err.message : err}`);
    }
  }

  function handleLoadHistory() {
    if (!startInput || !endInput) return;
    const start = new Date(startInput).toISOString();
    const end   = new Date(endInput).toISOString();
    setTimeRange({ start, end });
  }

  function handleGoLive() {
    setTimeRange(null);
  }

  const isLive = timeRange === null;

  return (
    <div class="view-mode">
      <header class="toolbar">
        <div class="toolbar-left">
          <span class="app-name">uopi</span>
          {currentInterface && (
            <span class="iface-name">{currentInterface.name}</span>
          )}
        </div>
        <div class="toolbar-center">
          {parseError && (
            <span class="parse-error" title={parseError}>Parse error — check console</span>
          )}
        </div>
        <div class="toolbar-right">
          <div
            class={`status-chip ${wsStatus}`}
            title={me.user ? `Signed in as ${me.user}${writable ? '' : ' (read-only)'}` : undefined}
          >
            <span class="status-dot"></span>
            {wsStatus === 'connected' && me.user ? `connected as ${me.user}` : wsStatus}
            {me.user && !writable && ' (read-only)'}
          </div>
          <button
            class={`toolbar-btn${showTimeNav ? ' toolbar-btn-active' : ''}`}
            title="Toggle historical time navigation"
            onClick={() => setShowTimeNav(v => !v)}
          >
            ⏱ History
          </button>
          <button
            class="icon-btn help-manual-btn"
            onClick={() => openHelp('start')}
            title="Open user manual"
          >
            📖
          </button>
          <ZoomControl />
          {writable && me.canEditLogic && (
            <button
              class="toolbar-btn"
              onClick={() => setShowControlLogic(true)}
              title="Open server-side control logic"
            >
              ⚙ Control logic
            </button>
          )}
          {me.canViewAudit && (
            <button
              class="toolbar-btn"
              onClick={() => setShowAudit(true)}
              title="View the audit log"
            >
              🛡 Audit
            </button>
          )}
          {writable && (
            <button
              class="toolbar-btn"
              onClick={() => setShowConfig(true)}
              title="Open configuration manager"
            >
              🗂 Config
            </button>
          )}
          {writable && (
            <button
              class="btn-edit"
              onClick={() => onEdit?.(currentInterface ?? undefined)}
              title="Switch to Edit mode"
            >
              Edit
            </button>
          )}
        </div>
      </header>

      {/* Historical time range bar — hidden by default */}
      {showTimeNav && (
        <div class="time-nav-bar">
          <button
            class={`toolbar-btn${isLive ? ' toolbar-btn-active' : ''}`}
            title="Switch to live data"
            onClick={handleGoLive}
          >
            ● Live
          </button>
          <input
            class="time-input"
            type="datetime-local"
            value={startInput}
            onInput={(e) => setStartInput((e.target as HTMLInputElement).value)}
            title="History start"
          />
          <span class="time-sep">→</span>
          <input
            class="time-input"
            type="datetime-local"
            value={endInput}
            onInput={(e) => setEndInput((e.target as HTMLInputElement).value)}
            title="History end"
          />
          <button
            class="toolbar-btn"
            title="Load historical data for this time range"
            onClick={handleLoadHistory}
          >
            Load
          </button>
        </div>
      )}

      <div class="content">
        <InterfaceList
          onLoad={handleLoad}
          onEdit={onEdit}
          onNewPlot={() => onEdit?.(newPlotPanel())}
          onEditId={handleEditById}
          width={leftW}
          collapsed={listCollapsed}
          onToggleCollapse={() => setListCollapsed(c => !c)}
          onSelect={async (id) => {
            try {
              const res = await fetch(`/api/v1/interfaces/${encodeURIComponent(id)}`);
              if (!res.ok) throw new Error(`HTTP ${res.status}`);
              handleLoad(await res.text());
            } catch (err) {
              setParseError(`Failed to load interface "${id}": ${err instanceof Error ? err.message : err}`);
            }
          }}
        />
        <div class="panel-resize-handle" onMouseDown={startResize} />

        <div class="view-content-area">
          <div class="view-panel-container active">
            <Canvas
              iface={currentInterface}
              onNavigate={handleNavigate}
              timeRange={timeRange}
            />
          </div>
        </div>
      </div>

      {showHelp && (
        <HelpModal initialSection={helpSection} onClose={() => setShowHelp(false)} />
      )}

      {showControlLogic && (
        <ControlLogicEditor onClose={() => setShowControlLogic(false)} />
      )}

      {showAudit && (
        <AuditViewer onClose={() => setShowAudit(false)} />
      )}
      {showConfig && (
        <ConfigManager onClose={() => setShowConfig(false)} />
      )}
    </div>
  );
}
