import { h } from 'preact';
import { useEffect } from 'preact/hooks';
import type { Interface, Widget, SignalRef, PlotLayout } from './lib/types';
import PlotWidget from './widgets/PlotWidget';
import SplitLayout from './SplitLayout';
import { genWidgetId } from './EditCanvas';
import { splitLeaf, removeLeaf, setRatioAtPath, countLeaves } from './lib/plotLayout';

interface Props {
  iface: Interface;
  selectedIds: string[];
  onSelect: (ids: string[]) => void;
  /** Apply a combined widgets + layout change as one undoable step. */
  onChange: (widgets: Widget[], layout: PlotLayout) => void;
}

function newPlotWidget(): Widget {
  return {
    id: genWidgetId(),
    type: 'plot',
    x: 0, y: 0, w: 800, h: 500,
    signals: [],
    options: { plotType: 'timeseries', timeWindow: '60', legend: 'bottom' },
  };
}

export default function PlotPanelCanvas({ iface, selectedIds, onSelect, onChange }: Props) {
  const layout = iface.layout ?? { type: 'leaf', widget: iface.widgets[0]?.id ?? '' };
  const byId = new Map(iface.widgets.map(w => [w.id, w]));
  const single = countLeaves(layout) <= 1;

  // When there is only one pane, it is always the selected one. Also recover
  // from a selection that points at a widget no longer present in this panel.
  useEffect(() => {
    const onlyId = single ? (layout.type === 'leaf' ? layout.widget : iface.widgets[0]?.id) : null;
    if (onlyId && selectedIds[0] !== onlyId) {
      onSelect([onlyId]);
    } else if (!single && selectedIds.length === 1 && !byId.has(selectedIds[0])) {
      onSelect([]);
    }
  }, [single, layout, selectedIds.join(',')]);

  function handleSplit(widgetId: string, dir: 'h' | 'v') {
    const w = newPlotWidget();
    const nextLayout = splitLeaf(layout, widgetId, dir, w.id);
    onChange([...iface.widgets, w], nextLayout);
    onSelect([w.id]);
  }

  function handleClose(widgetId: string) {
    if (single) return;
    const nextLayout = removeLeaf(layout, widgetId);
    onChange(iface.widgets.filter(w => w.id !== widgetId), nextLayout);
    onSelect([]);
  }

  function handleResize(path: number[], ratio: number) {
    onChange(iface.widgets, setRatioAtPath(layout, path, ratio));
  }

  function handleDrop(e: DragEvent, widget: Widget) {
    e.preventDefault();
    e.stopPropagation();
    const json = e.dataTransfer?.getData('application/json');
    if (!json) return;
    let sig: SignalRef;
    try { sig = JSON.parse(json); } catch { return; }
    if (widget.signals.some(s => s.ds === sig.ds && s.name === sig.name)) return;
    const updated = { ...widget, signals: [...widget.signals, sig] };
    onChange(iface.widgets.map(w => w.id === updated.id ? updated : w), layout);
    onSelect([updated.id]);
  }

  function renderLeaf(widgetId: string) {
    const widget = byId.get(widgetId);
    const selected = selectedIds.includes(widgetId);
    return (
      <div
        class={`plot-pane${selected ? ' plot-pane-selected' : ''}`}
        onMouseDownCapture={() => onSelect([widgetId])}
        onDragOver={(e: DragEvent) => { e.preventDefault(); if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'; }}
        onDrop={(e: DragEvent) => widget && handleDrop(e, widget)}
      >
        {selected && <div class="plot-pane-badge">editing</div>}
        {widget
          ? <PlotWidget widget={widget} timeRange={null} />
          : <div class="plot-pane-empty">missing plot</div>}

        <div class="plot-pane-overlay" onMouseDown={(e: MouseEvent) => e.stopPropagation()}>
          <button class="plot-pane-btn" title="Split left/right" onClick={() => handleSplit(widgetId, 'h')}>⬌</button>
          <button class="plot-pane-btn" title="Split top/bottom" onClick={() => handleSplit(widgetId, 'v')}>⬍</button>
          <button class="plot-pane-btn" title="Remove this plot" disabled={single} onClick={() => handleClose(widgetId)}>✕</button>
        </div>

        {widget && widget.signals.length === 0 && (
          <div class="plot-pane-hint">Drag a signal here, then configure it in the properties pane →</div>
        )}
      </div>
    );
  }

  return (
    <div class="plot-panel-edit">
      <SplitLayout layout={layout} renderLeaf={renderLeaf} onResize={handleResize} />
    </div>
  );
}
