// table-resize.jsx — Reusable column resizing for data tables.
//
// Usage in a screen:
//
//   const { widths, getThProps } = window.useColumnWidths("pipeline", {
//     target: 240, buyer: 200, status: 170, ...
//   });
//
//   <thead><tr>
//     <th {...getThProps("target")}>Target</th>
//     <th {...getThProps("buyer")}>Buyer</th>
//     ...
//   </tr></thead>
//
// Behavior:
// - Drag right edge to resize column
// - Double-click right edge to auto-size to content
// - Widths persist to localStorage per tableId
// - All users share the same default widths until they customize

(function () {
  const { useState, useEffect, useCallback, useRef } = React;

  const MIN_WIDTH = 40;
  const MAX_WIDTH = 800;
  const STORAGE_PREFIX = "vault.colwidths.";

  // ---- Hook: useColumnWidths ----
  window.useColumnWidths = function useColumnWidths(tableId, defaults) {
    const storageKey = STORAGE_PREFIX + tableId;

    // Initial state: load from localStorage, falling back to defaults
    const [widths, setWidths] = useState(() => {
      try {
        const stored = JSON.parse(localStorage.getItem(storageKey) || "{}");
        return { ...defaults, ...stored };
      } catch (e) {
        return { ...defaults };
      }
    });

    // Persist whenever widths change
    useEffect(() => {
      try {
        // Only persist columns that differ from defaults (keep storage small)
        const overrides = {};
        for (const k of Object.keys(widths)) {
          if (widths[k] !== defaults[k]) overrides[k] = widths[k];
        }
        if (Object.keys(overrides).length === 0) {
          localStorage.removeItem(storageKey);
        } else {
          localStorage.setItem(storageKey, JSON.stringify(overrides));
        }
      } catch (e) {
        // ignore quota errors
      }
    }, [widths, storageKey, defaults]);

    const setWidth = useCallback((col, w) => {
      const clamped = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, Math.round(w)));
      setWidths(prev => ({ ...prev, [col]: clamped }));
    }, []);

    const resetAll = useCallback(() => {
      setWidths({ ...defaults });
      try { localStorage.removeItem(storageKey); } catch (e) {}
    }, [defaults, storageKey]);

    // Build props for a <th>: returns { style, children: [drag handle] }
    // Caller spreads into <th> and adds the label as a child.
    const getThProps = useCallback((col) => {
      const w = widths[col];
      return {
        style: w ? { width: w, minWidth: w, maxWidth: w, position: "relative" } : { position: "relative" },
        "data-col": col,
        ref: (el) => {
          // We don't keep refs; resize uses event delegation via the handle.
        },
      };
    }, [widths]);

    return { widths, setWidth, resetAll, getThProps };
  };

  // ---- Component: ResizeHandle ----
  // A vertical bar at the right edge of a <th>. Drag = resize. Double-click = auto-size.
  window.ResizeHandle = function ResizeHandle({ col, currentWidth, onResize, getMaxContentWidth }) {
    const startX = useRef(0);
    const startWidth = useRef(0);
    const dragging = useRef(false);

    const onMouseDown = useCallback((e) => {
      e.preventDefault();
      e.stopPropagation();
      startX.current = e.clientX;
      startWidth.current = currentWidth;
      dragging.current = true;
      document.body.style.cursor = "col-resize";
      document.body.style.userSelect = "none";

      const onMove = (mv) => {
        if (!dragging.current) return;
        const delta = mv.clientX - startX.current;
        onResize(col, startWidth.current + delta);
      };
      const onUp = () => {
        dragging.current = false;
        document.body.style.cursor = "";
        document.body.style.userSelect = "";
        document.removeEventListener("mousemove", onMove);
        document.removeEventListener("mouseup", onUp);
      };
      document.addEventListener("mousemove", onMove);
      document.addEventListener("mouseup", onUp);
    }, [col, currentWidth, onResize]);

    const onDoubleClick = useCallback((e) => {
      e.preventDefault();
      e.stopPropagation();
      // Auto-size: walk the column cells and find the widest content.
      // We measure by temporarily setting the column to a large width, then
      // reading the natural width of each cell.
      const th = e.currentTarget.parentElement;
      if (!th) return;
      const table = th.closest("table");
      if (!table) return;

      const thIndex = Array.from(th.parentElement.children).indexOf(th);
      let maxWidth = 0;
      // Header label width
      const headerLabel = th.querySelector("button, span, .th-label");
      if (headerLabel) {
        maxWidth = Math.max(maxWidth, headerLabel.scrollWidth);
      } else {
        maxWidth = Math.max(maxWidth, th.scrollWidth);
      }
      // Body cell widths
      const rows = table.querySelectorAll("tbody tr");
      rows.forEach(row => {
        const cell = row.children[thIndex];
        if (!cell) return;
        // Use scrollWidth which is the unconstrained content width
        maxWidth = Math.max(maxWidth, cell.scrollWidth);
      });
      // Padding allowance
      onResize(col, maxWidth + 28);
    }, [col, onResize]);

    return React.createElement("div", {
      onMouseDown,
      onDoubleClick,
      title: "Drag to resize · double-click to auto-size",
      style: {
        position: "absolute",
        top: 0,
        right: -3,
        width: 6,
        height: "100%",
        cursor: "col-resize",
        zIndex: 5,
        background: "transparent",
      },
      onMouseEnter: (e) => { e.currentTarget.style.background = "var(--accent-soft)"; },
      onMouseLeave: (e) => { if (!dragging.current) e.currentTarget.style.background = "transparent"; },
    });
  };

  // ---- Convenience: ResizableTh ----
  // Wraps both the <th> styling + drag handle. Caller passes col + label.
  //
  //   <ResizableTh col="target" widths={widths} setWidth={setWidth}>Target</ResizableTh>
  //
  // Equivalent to writing a <th> manually with getThProps spread.
  window.ResizableTh = function ResizableTh({ col, widths, setWidth, children, className, align, ...rest }) {
    const w = widths[col];
    return React.createElement("th",
      {
        className: align === "r" ? (className || "") + " r" : className,
        style: w ? { width: w, minWidth: w, maxWidth: w, position: "relative", ...rest.style } : { position: "relative", ...rest.style },
        "data-col": col,
        ...rest,
      },
      children,
      React.createElement(window.ResizeHandle, { col, currentWidth: w || 100, onResize: setWidth })
    );
  };

})();
