import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import { getSignalStore, getMetaStore } from '../lib/stores';
import { formatValue } from '../lib/format';
import type { Widget, SignalRef, SignalValue, SignalMeta } from '../lib/types';

const DEFAULT_VALUE: SignalValue = { value: null, quality: 'unknown', ts: null };

const COLS = ['name', 'value', 'unit', 'quality', 'time'] as const;
type Col = typeof COLS[number];

const COL_LABELS: Record<Col, string> = {
  name: 'Name', value: 'Value', unit: 'Unit', quality: 'Status', time: 'Time',
};

function qualityColor(q: string): string {
  switch (q) {
    case 'good': return '#4ade80';
    case 'uncertain': return '#fbbf24';
    case 'bad': return '#f87171';
    default: return '#6b7280';
  }
}

function isCol(c: string): c is Col {
  return (COLS as readonly string[]).includes(c);
}

interface RowProps {
  sig: SignalRef;
  label: string;
  cols: Col[];
  fmt: string;
  unitOverride: string;
}

// One subscribed row. Each row owns its own value/meta subscription so the
// table can carry an arbitrary number of unrelated signals.
function TableRow({ sig, label, cols, fmt, unitOverride }: RowProps) {
  const [sv, setSv] = useState<SignalValue>(DEFAULT_VALUE);
  const [meta, setMeta] = useState<SignalMeta | null>(null);

  useEffect(() => {
    const uv = getSignalStore(sig).subscribe(setSv);
    const um = getMetaStore(sig).subscribe(setMeta);
    return () => { uv(); um(); };
  }, [sig.ds, sig.name]);

  function valStr(): string {
    const v = sv.value;
    if (v === null || v === undefined) return '---';
    if (typeof v === 'number') return formatValue(v, fmt);
    if (Array.isArray(v)) return `[${v.length}]`;
    return String(v);
  }

  const unit = unitOverride === 'none' ? '' : (unitOverride || meta?.unit || '');
  const time = sv.ts ? new Date(sv.ts).toLocaleTimeString() : '';

  return (
    <tr>
      {cols.map(c => {
        switch (c) {
          case 'name':
            return <td key={c} class="tw-name" title={`${sig.ds}:${sig.name}`}>{label}</td>;
          case 'value':
            return <td key={c} class="tw-value">{valStr()}</td>;
          case 'unit':
            return <td key={c} class="tw-unit">{unit}</td>;
          case 'quality':
            return (
              <td key={c} class="tw-quality">
                <span class="quality-dot" style={`background:${qualityColor(sv.quality)};`} title={`Quality: ${sv.quality}`} />
              </td>
            );
          case 'time':
            return <td key={c} class="tw-time">{time}</td>;
        }
      })}
    </tr>
  );
}

interface Props { widget: Widget; onContextMenu?: (e: MouseEvent) => void; }

// A tabular multi-signal readout: each bound signal is one row, with a
// configurable set of columns (name / value / unit / status / time).
export default function TableWidget({ widget, onContextMenu }: Props) {
  const o = widget.options;
  const parsed = (o['columns'] ?? 'name,value,unit')
    .split(',').map(s => s.trim()).filter(isCol);
  const cols: Col[] = parsed.length ? parsed : ['name', 'value'];
  const showHeader = o['header'] !== 'false';
  const title = o['title'] ?? '';
  const fmt = o['format'] ?? '';
  const unitOverride = o['unit'] ?? '';
  const labels = (o['labels'] ?? '').split(',');

  return (
    <div
      class="table-widget"
      style={`left:${widget.x}px;top:${widget.y}px;width:${widget.w}px;height:${widget.h}px;`}
      onContextMenu={onContextMenu}
    >
      {title && <div class="tw-title">{title}</div>}
      <div class="tw-scroll">
        <table class="tw-table">
          {showHeader && (
            <thead>
              <tr>{cols.map(c => <th key={c} class={`tw-th-${c}`}>{COL_LABELS[c]}</th>)}</tr>
            </thead>
          )}
          <tbody>
            {widget.signals.length === 0 ? (
              <tr><td class="tw-empty" colSpan={cols.length}>No signals — drop signals here</td></tr>
            ) : (
              widget.signals.map((s, i) => (
                <TableRow
                  key={`${s.ds}:${s.name}`}
                  sig={s}
                  label={labels[i]?.trim() || s.name}
                  cols={cols}
                  fmt={fmt}
                  unitOverride={unitOverride}
                />
              ))
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}
