import { useEffect, useMemo, useRef, useState } from "react";
import { Document, Page, pdfjs } from "react-pdf";
import workerSrc from "pdfjs-dist/build/pdf.worker.min.mjs?url";

import "react-pdf/dist/Page/AnnotationLayer.css";
import "react-pdf/dist/Page/TextLayer.css";

pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;

/**
 * FIELDS:
 * - scalar fields use: anchor + value (stored as offset from anchor)
 * - items uses: table + header + anchors + columns (+ row_height_hint)
 */
const FIELDS = [
  { fieldId: "facility_organization", label: "Facility / Organization", type: "entity" },
  { fieldId: "case_location", label: "Case Location / Address", type: "text" },
  { fieldId: "vendor", label: "Vendor", type: "entity" },
  { fieldId: "physician_name", label: "Physician Name", type: "person" },
  { fieldId: "date_of_surgery", label: "Date of Surgery", type: "date" },
  { fieldId: "items", label: "Items / Line Items", type: "table" },
];

// Table config keys (trainer only)
const TABLE_ANCHORS = [
  { key: "item_number", expected_text: "Item Number" },
  { key: "description", expected_text: "Description" },
  { key: "qty", expected_text: "Qty" },
];

const TABLE_COLUMNS = [
  { key: "item_number", label: "Item Number" },
  { key: "description", label: "Description" },
  { key: "qty", label: "Qty" },
];

/** ---------- normalization helpers ---------- */

function normBBox(b, w, h) {
  return {
    x: +(b.x / w).toFixed(6),
    y: +(b.y / h).toFixed(6),
    w: +(b.w / w).toFixed(6),
    h: +(b.h / h).toFixed(6),
  };
}

function normOffset(dx, dy, w, h, pageW, pageH) {
  return {
    dx: +(dx / pageW).toFixed(6),
    dy: +(dy / pageH).toFixed(6),
    w: +(w / pageW).toFixed(6),
    h: +(h / pageH).toFixed(6),
  };
}

function applyOffset(anchorBox, offsetPx) {
  if (!anchorBox || !offsetPx) return null;
  return {
    x: anchorBox.x + offsetPx.dx,
    y: anchorBox.y + offsetPx.dy,
    w: offsetPx.w,
    h: offsetPx.h,
  };
}

function toRelativeBBox(childAbs, parentAbs) {
  if (!childAbs || !parentAbs) return null;
  return {
    x: childAbs.x - parentAbs.x,
    y: childAbs.y - parentAbs.y,
    w: childAbs.w,
    h: childAbs.h,
  };
}

function clampBBoxToParent(childAbs, parentAbs) {
  if (!childAbs || !parentAbs) return childAbs;
  const x = Math.max(parentAbs.x, Math.min(childAbs.x, parentAbs.x + parentAbs.w));
  const y = Math.max(parentAbs.y, Math.min(childAbs.y, parentAbs.y + parentAbs.h));
  const x2 = Math.max(parentAbs.x, Math.min(childAbs.x + childAbs.w, parentAbs.x + parentAbs.w));
  const y2 = Math.max(parentAbs.y, Math.min(childAbs.y + childAbs.h, parentAbs.y + parentAbs.h));
  return { x, y, w: Math.max(0, x2 - x), h: Math.max(0, y2 - y) };
}

/** ---------- UI styles ---------- */

const UI = {
  panelBg: "#141414",
  panelText: "#EDEDED",
  subtle: "#A7A7A7",
  border: "rgba(255,255,255,0.10)",

  btnBase: {
    width: "100%",
    padding: "10px 12px",
    borderRadius: 10,
    border: "1px solid rgba(255,255,255,0.15)",
    fontWeight: 700,
    cursor: "pointer",
    userSelect: "none",
  },

  greenDark: { background: "#0f7a36", color: "#fff" },
  blue: { background: "#2563eb", color: "#fff" },
  green2: { background: "#22c55e", color: "#fff" },
  purple: { background: "#7c3aed", color: "#fff" },
  orange: { background: "#f59e0b", color: "#111" },
  teal: { background: "#14b8a6", color: "#081016" },
  gray: { background: "rgba(255,255,255,0.08)", color: "#fff" },

  pill: (active, colorObj) => ({
    padding: "8px 10px",
    borderRadius: 10,
    border: active ? "1px solid rgba(255,255,255,0.35)" : "1px solid rgba(255,255,255,0.15)",
    ...colorObj,
    opacity: active ? 1 : 0.65,
    cursor: "pointer",
    flex: 1,
    fontWeight: 800,
    textAlign: "center",
  }),

  label: { fontSize: 12, color: "#CFCFCF", marginBottom: 6, fontWeight: 700 },
  input: {
    width: "100%",
    padding: 10,
    borderRadius: 10,
    border: "1px solid rgba(255,255,255,0.12)",
    background: "rgba(255,255,255,0.06)",
    color: "#fff",
    outline: "none",
  },
  select: {
    width: "100%",
    padding: 10,
    borderRadius: 10,
    border: "1px solid rgba(255,255,255,0.12)",
    background: "rgba(255,255,255,0.06)",
    color: "#fff",
    outline: "none",
  },
};

function isTableField(field) {
  return field?.type === "table";
}

const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:8000";

export default function App() {
  // PDF comes from pdf_id in URL
  const [pdfId, setPdfId] = useState(null);
  const [pdfUrl, setPdfUrl] = useState(null);
  const [pdfName, setPdfName] = useState(null);

  // NEW: template id comes from URL OR manual input
  const [templateId, setTemplateId] = useState("");

  const [pageSize, setPageSize] = useState({ w: 0, h: 0 });
  const [selectedFieldId, setSelectedFieldId] = useState(FIELDS[0].fieldId);

  const [scalarMode, setScalarMode] = useState("anchor"); // anchor | value

  const [tableMode, setTableMode] = useState("table"); // table | header | anchor | column
  const [selectedTableAnchorKey, setSelectedTableAnchorKey] = useState(TABLE_ANCHORS[0].key);
  const [selectedColumnKey, setSelectedColumnKey] = useState(TABLE_COLUMNS[0].key);

  const [offsetMode, setOffsetMode] = useState(true);
  const [rowHeightHintPx, setRowHeightHintPx] = useState(0);

  const [scale, setScale] = useState(1);
  const [pan, setPan] = useState({ x: 0, y: 0 });
  const [spaceDown, setSpaceDown] = useState(false);
  const [isPanning, setIsPanning] = useState(false);
  const panStartRef = useRef(null);
  const stageRef = useRef(null);

  const [draft, setDraft] = useState(null);
  const dragStartRef = useRef(null);
  const overlayRef = useRef(null);

  const [showPreview, setShowPreview] = useState(true);

  const [sendStatus, setSendStatus] = useState({ state: "idle", msg: "" }); // idle|sending|ok|err

  const [boxes, setBoxes] = useState(() => {
    const o = {};
    for (const f of FIELDS) {
      if (f.type === "table") {
        const anchorsAbs = {};
        for (const a of TABLE_ANCHORS) anchorsAbs[a.key] = null;

        const columnsAbs = {};
        for (const c of TABLE_COLUMNS) columnsAbs[c.key] = null;

        o[f.fieldId] = {
          kind: "table",
          tableAbs: null,
          headerAbs: null,
          anchorsAbs,
          columnsAbs,
        };
      } else {
        o[f.fieldId] = {
          kind: "scalar",
          anchor: null,
          valueAbs: null,
          valueOffsetPx: null,
        };
      }
    }
    return o;
  });

  // Spacebar handling for pan
  useEffect(() => {
    function onKeyDown(e) {
      if (e.code === "Space") {
        e.preventDefault();
        setSpaceDown(true);
      }
    }
    function onKeyUp(e) {
      if (e.code === "Space") {
        e.preventDefault();
        setSpaceDown(false);
        setIsPanning(false);
        panStartRef.current = null;
      }
    }
    window.addEventListener("keydown", onKeyDown, { passive: false });
    window.addEventListener("keyup", onKeyUp, { passive: false });
    return () => {
      window.removeEventListener("keydown", onKeyDown);
      window.removeEventListener("keyup", onKeyUp);
    };
  }, []);

  // Read pdf_id + template_id from URL and load PDF from backend
  useEffect(() => {
    const sp = new URLSearchParams(window.location.search);

    console.log("URL", window.location.href);
    console.log("query", Object.fromEntries(sp.entries()));
    const id = sp.get("pdf_id") || sp.get("id") || sp.get("pdfId") || sp.get("pdf");
    setPdfId(id || null);

    const tid = sp.get("template_id");
    setTemplateId((tid || "").trim());

    if (!id) {
      setPdfUrl(null);
      setPdfName(null);
      return;
    }

    let alive = true;
    let objectUrl = null;

    async function loadPdf() {
      try {
        const resp = await fetch(`${API_BASE}/api/pdf/${encodeURIComponent(id)}`);
        if (!resp.ok) throw new Error(`Failed to fetch PDF (${resp.status})`);
        const name = resp.headers.get("X-PDF-Name") || `document_${id}.pdf`;
        const blob = await resp.blob();
        objectUrl = URL.createObjectURL(blob);
        if (!alive) return;

        setPdfUrl(objectUrl);
        setPdfName(name);

        setScale(1);
        setPan({ x: 0, y: 0 });
      } catch (e) {
        console.error(e);
        if (!alive) return;
        setPdfUrl(null);
        setPdfName(null);
      }
    }

    loadPdf();

    return () => {
      alive = false;
      if (objectUrl) URL.revokeObjectURL(objectUrl);
    };
  }, []);

  const selectedField = useMemo(
    () => FIELDS.find((f) => f.fieldId === selectedFieldId),
    [selectedFieldId]
  );
  const selectedIsTable = isTableField(selectedField);

  function getPoint(e) {
    const el = overlayRef.current;
    if (!el) return null;
    const r = el.getBoundingClientRect();

    const mx = e.clientX - r.left;
    const my = e.clientY - r.top;

    const x = mx / scale;
    const y = my / scale;

    return {
      x: Math.max(0, Math.min(x, pageSize.w)),
      y: Math.max(0, Math.min(y, pageSize.h)),
    };
  }

  function onMouseDown(e) {
    if (!pdfUrl || !pageSize.w || !pageSize.h) return;

    if (spaceDown) {
      setIsPanning(true);
      panStartRef.current = {
        mouseX: e.clientX,
        mouseY: e.clientY,
        panX: pan.x,
        panY: pan.y,
      };
      return;
    }

    const p = getPoint(e);
    if (!p) return;
    dragStartRef.current = p;
    setDraft({ x: p.x, y: p.y, w: 0, h: 0 });
  }

  function onMouseMove(e) {
    if (isPanning && panStartRef.current) {
      const s = panStartRef.current;
      const dx = e.clientX - s.mouseX;
      const dy = e.clientY - s.mouseY;
      setPan({ x: s.panX + dx, y: s.panY + dy });
      return;
    }

    if (!dragStartRef.current) return;
    const p = getPoint(e);
    if (!p) return;

    const s = dragStartRef.current;
    const x1 = Math.min(s.x, p.x);
    const y1 = Math.min(s.y, p.y);
    const x2 = Math.max(s.x, p.x);
    const y2 = Math.max(s.y, p.y);

    setDraft({ x: x1, y: y1, w: x2 - x1, h: y2 - y1 });
  }

  function onMouseUp() {
    if (isPanning) {
      setIsPanning(false);
      panStartRef.current = null;
      return;
    }

    if (!dragStartRef.current) return;
    dragStartRef.current = null;

    if (!draft || draft.w < 8 || draft.h < 8) {
      setDraft(null);
      return;
    }

    setBoxes((prev) => {
      const next = structuredClone(prev);
      const st = next[selectedFieldId];
      if (!st) return prev;

      if (selectedIsTable && st.kind === "table") {
        if (tableMode === "table") {
          st.tableAbs = draft;

          if (st.headerAbs) st.headerAbs = clampBBoxToParent(st.headerAbs, st.tableAbs);
          for (const k of Object.keys(st.anchorsAbs)) {
            if (st.anchorsAbs[k]) st.anchorsAbs[k] = clampBBoxToParent(st.anchorsAbs[k], st.tableAbs);
          }
          for (const k of Object.keys(st.columnsAbs)) {
            if (st.columnsAbs[k]) st.columnsAbs[k] = clampBBoxToParent(st.columnsAbs[k], st.tableAbs);
          }
        }

        if (tableMode === "header") {
          st.headerAbs = st.tableAbs ? clampBBoxToParent(draft, st.tableAbs) : draft;
        }

        if (tableMode === "anchor") {
          const key = selectedTableAnchorKey;
          st.anchorsAbs[key] = st.tableAbs ? clampBBoxToParent(draft, st.tableAbs) : draft;
        }

        if (tableMode === "column") {
          const key = selectedColumnKey;
          st.columnsAbs[key] = st.tableAbs ? clampBBoxToParent(draft, st.tableAbs) : draft;
        }

        next[selectedFieldId] = st;
        return next;
      }

      if (!selectedIsTable && st.kind === "scalar") {
        if (scalarMode === "anchor") {
          st.anchor = draft;
        } else {
          if (offsetMode) {
            if (!st.anchor) {
              st.valueAbs = draft;
              st.valueOffsetPx = null;
            } else {
              st.valueOffsetPx = {
                dx: draft.x - st.anchor.x,
                dy: draft.y - st.anchor.y,
                w: draft.w,
                h: draft.h,
              };
              st.valueAbs = null;
            }
          } else {
            st.valueAbs = draft;
            st.valueOffsetPx = null;
          }
        }

        next[selectedFieldId] = st;
        return next;
      }

      return prev;
    });

    setDraft(null);
  }

  function clearCurrent(kind) {
    setBoxes((prev) => {
      const next = structuredClone(prev);
      const st = next[selectedFieldId];
      if (!st) return prev;

      if (selectedIsTable && st.kind === "table") {
        if (kind === "table") st.tableAbs = null;
        if (kind === "header") st.headerAbs = null;
        if (kind === "anchor") st.anchorsAbs[selectedTableAnchorKey] = null;
        if (kind === "column") st.columnsAbs[selectedColumnKey] = null;
        return next;
      }

      if (!selectedIsTable && st.kind === "scalar") {
        if (kind === "anchor") st.anchor = null;
        if (kind === "value") {
          st.valueAbs = null;
          st.valueOffsetPx = null;
        }
        return next;
      }

      return prev;
    });
  }

  function getScalarDisplayValueBox(fieldId) {
    const st = boxes[fieldId];
    if (!st || st.kind !== "scalar") return null;
    if (!offsetMode) return st.valueAbs;
    return applyOffset(st.anchor, st.valueOffsetPx);
  }

  function buildConfig() {
    if (!pageSize.w || !pageSize.h) return null;

    return {
      form_id: pdfId ? `trainer_${pdfId}` : "trainer_form_v1",
      version: 3,
      page: 1,
      scalar_value_region_mode: offsetMode ? "offset_from_anchor_v1" : "absolute_bbox_v1",
      fields: FIELDS.map((f) => {
        const st = boxes[f.fieldId];

        if (f.type === "table" && st?.kind === "table") {
          const tableAbs = st.tableAbs;
          const headerAbs = st.headerAbs;

          const table_bbox_norm = tableAbs ? normBBox(tableAbs, pageSize.w, pageSize.h) : null;
          const header_bbox_norm = headerAbs ? normBBox(headerAbs, pageSize.w, pageSize.h) : null;

          const row_height_hint_norm =
            rowHeightHintPx > 0 ? +(rowHeightHintPx / pageSize.h).toFixed(6) : null;

          const table_anchors = TABLE_ANCHORS.map((a) => {
            const abs = st.anchorsAbs[a.key];
            return {
              key: a.key,
              expected_text: a.expected_text,
              bbox_norm: abs ? normBBox(abs, pageSize.w, pageSize.h) : null,
            };
          });

          const columns =
            tableAbs
              ? TABLE_COLUMNS.map((c) => {
                  const abs = st.columnsAbs[c.key];
                  const rel = abs ? toRelativeBBox(abs, tableAbs) : null;
                  return {
                    key: c.key,
                    label: c.label,
                    bbox_rel_norm: rel ? normBBox(rel, tableAbs.w, tableAbs.h) : null,
                  };
                })
              : TABLE_COLUMNS.map((c) => ({
                  key: c.key,
                  label: c.label,
                  bbox_rel_norm: null,
                }));

          return {
            field_id: f.fieldId,
            label: f.label,
            type: f.type,
            table_bbox_norm,
            header_bbox_norm,
            row_height_hint_norm,
            columns,
            table_anchors,
            notes: "Anchors are used at runtime to localize table/header/columns under drift.",
          };
        }

        if (st?.kind === "scalar") {
          const anchorNorm = st.anchor ? normBBox(st.anchor, pageSize.w, pageSize.h) : null;
          const valueAbsNorm = st.valueAbs ? normBBox(st.valueAbs, pageSize.w, pageSize.h) : null;

          const valueOffsetNorm =
            st.valueOffsetPx && offsetMode
              ? normOffset(
                  st.valueOffsetPx.dx,
                  st.valueOffsetPx.dy,
                  st.valueOffsetPx.w,
                  st.valueOffsetPx.h,
                  pageSize.w,
                  pageSize.h
                )
              : null;

          return {
            field_id: f.fieldId,
            label: f.label,
            type: f.type,
            anchor_bbox_norm: anchorNorm,
            value_bbox_norm: offsetMode ? null : valueAbsNorm,
            value_offset_norm: offsetMode ? valueOffsetNorm : null,
          };
        }

        return { field_id: f.fieldId, label: f.label, type: f.type };
      }),
      notes:
        "Trainer exports config only. Runtime should localize anchors then apply offsets/table mappings to extract values + line items.",
    };
  }

  const previewConfig = useMemo(
    () => buildConfig(),
    [pageSize.w, pageSize.h, boxes, offsetMode, rowHeightHintPx, pdfId]
  );

  async function saveConfig() {
    if (!pdfId) {
      setSendStatus({ state: "err", msg: "Missing pdf_id in URL." });
      return;
    }
    const tid = (templateId || "").trim();
    if (!tid) {
      setSendStatus({ state: "err", msg: "Missing template_id. Add ?template_id=... or type it in the left panel." });
      return;
    }

    const cfg = buildConfig();
    if (!cfg) {
      setSendStatus({ state: "err", msg: "Config not ready. PDF not loaded or page size missing." });
      return;
    }

    setSendStatus({ state: "sending", msg: "Saving..." });

    try {
      const resp = await fetch(`${API_BASE}/api/send-config`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ pdf_id: pdfId, template_id: tid, config: cfg }),
      });

      if (!resp.ok) {
        const t = await resp.text();
        throw new Error(`Save failed (${resp.status}): ${t}`);
      }

      const data = await resp.json().catch(() => ({}));
      setSendStatus({ state: "ok", msg: data?.message || "Saved." });
    } catch (e) {
      console.error(e);
      setSendStatus({ state: "err", msg: e.message || "Save failed." });
    }
  }

  const drawModeTitle = useMemo(() => {
    if (!selectedField) return "";
    if (selectedIsTable) return "Draw Mode (Table)";
    return "Draw Mode (Scalar)";
  }, [selectedField, selectedIsTable]);

  const activeModeLabel = useMemo(() => {
    if (!selectedField) return "";
    if (!selectedIsTable) return scalarMode === "anchor" ? "Anchor (Blue)" : "Value (Green)";
    if (tableMode === "table") return "Table Region (Purple)";
    if (tableMode === "header") return "Header Row (Orange)";
    if (tableMode === "anchor") return `Table Anchor (Blue): ${selectedTableAnchorKey}`;
    if (tableMode === "column") return `Column (Teal): ${selectedColumnKey}`;
    return "";
  }, [selectedField, selectedIsTable, scalarMode, tableMode, selectedTableAnchorKey, selectedColumnKey]);

  return (
    <div style={{ display: "grid", gridTemplateColumns: "380px 1fr 420px", height: "100vh" }}>
      {/* Left panel */}
      <div
        style={{
          padding: 16,
          borderRight: `1px solid ${UI.border}`,
          overflow: "auto",
          background: UI.panelBg,
          color: UI.panelText,
        }}
      >
        <h2 style={{ margin: "0 0 14px", fontSize: 26, letterSpacing: 0.2 }}>PDF Trainer</h2>

        <div style={{ marginBottom: 14 }}>
          <div style={UI.label}>Document Source</div>
          <div style={{ fontSize: 12, color: UI.subtle, lineHeight: 1.4 }}>
            <b>pdf_id:</b> {pdfId || "—"}
            <br />
            <b>file:</b> {pdfName || "—"}
          </div>
          {!pdfId && (
            <div style={{ marginTop: 10, fontSize: 12, color: "#ffb4b4" }}>
              Missing <b>pdf_id</b>. Open this page using the pipeline link from the email.
            </div>
          )}
        </div>

        {/* NEW: Template ID */}
        <div style={{ marginBottom: 14 }}>
          <div style={UI.label}>Template ID (required)</div>
          <input
            style={{ ...UI.input, fontWeight: 800 }}
            value={templateId}
            onChange={(e) => setTemplateId(e.target.value)}
            placeholder="e.g. T1_IFACTOR_DELIVERED_ORDER"
          />
          <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
            Prefer URL: <code>?pdf_id=...&template_id=...</code>
          </div>
        </div>

        {/* Zoom / Pan controls */}
        <div style={{ marginBottom: 14 }}>
          <div style={UI.label}>View (Zoom / Pan)</div>

          <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
            <button
              type="button"
              onClick={() => setScale((s) => Math.max(0.5, +(s - 0.1).toFixed(2)))}
              style={{ ...UI.btnBase, ...UI.gray, width: 56, padding: "10px 0" }}
              title="Zoom out"
            >
              −
            </button>

            <input
              type="range"
              min="0.5"
              max="2.5"
              step="0.05"
              value={scale}
              onChange={(e) => setScale(+e.target.value)}
              style={{ width: "100%" }}
            />

            <button
              type="button"
              onClick={() => setScale((s) => Math.min(2.5, +(s + 0.1).toFixed(2)))}
              style={{ ...UI.btnBase, ...UI.gray, width: 56, padding: "10px 0" }}
              title="Zoom in"
            >
              +
            </button>
          </div>

          <div style={{ display: "flex", gap: 10, marginTop: 10 }}>
            <button
              type="button"
              onClick={() => {
                setScale(1);
                setPan({ x: 0, y: 0 });
              }}
              style={{ ...UI.btnBase, background: "#0f172a", color: "#fff" }}
            >
              Reset View (1x)
            </button>
          </div>

          <div style={{ fontSize: 12, color: UI.subtle, marginTop: 8 }}>
            Pan: hold <b>Space</b> and drag on the PDF.
          </div>
        </div>

        {!selectedIsTable && (
          <div style={{ marginBottom: 14 }}>
            <label style={{ display: "flex", gap: 10, alignItems: "center", fontSize: 12 }}>
              <input type="checkbox" checked={offsetMode} onChange={(e) => setOffsetMode(e.target.checked)} />
              <span style={{ fontWeight: 800 }}>Value follows anchor (offset mode)</span>
            </label>
            <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
              Offset mode = drift fix: store value region relative to anchor.
            </div>
          </div>
        )}

        {/* Field selector */}
        <div style={{ marginBottom: 14 }}>
          <div style={UI.label}>Field</div>
          <select
            value={selectedFieldId}
            onChange={(e) => setSelectedFieldId(e.target.value)}
            style={{ ...UI.select, padding: 14, fontSize: 16, fontWeight: 800 }}
          >
            {FIELDS.map((f) => (
              <option key={f.fieldId} value={f.fieldId}>
                {f.label}
              </option>
            ))}
          </select>
          <div style={{ fontSize: 12, color: UI.subtle, marginTop: 8 }}>
            Selected: <b style={{ color: "#fff" }}>{selectedField?.label}</b>{" "}
            <span style={{ color: UI.subtle }}>({selectedField?.type})</span>
          </div>
        </div>

        {selectedIsTable && (
          <div style={{ marginBottom: 14 }}>
            <div style={UI.label}>Row Height Hint (optional)</div>
            <input
              style={UI.input}
              type="number"
              min="0"
              step="1"
              value={rowHeightHintPx}
              onChange={(e) => setRowHeightHintPx(Number(e.target.value || 0))}
              placeholder="e.g. 28"
            />
            <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
              Used later to split rows. Leave 0 if unknown.
            </div>
          </div>
        )}

        {/* Draw mode */}
        <div style={{ marginBottom: 14 }}>
          <div style={UI.label}>{drawModeTitle}</div>

          {!selectedIsTable && (
            <div style={{ display: "flex", gap: 10 }}>
              <div role="button" onClick={() => setScalarMode("anchor")} style={UI.pill(scalarMode === "anchor", UI.blue)}>
                Anchor (Blue)
              </div>
              <div role="button" onClick={() => setScalarMode("value")} style={UI.pill(scalarMode === "value", UI.green2)}>
                Value (Green)
              </div>
            </div>
          )}

          {selectedIsTable && (
            <>
              <div style={{ display: "flex", gap: 10, marginBottom: 10 }}>
                <div role="button" onClick={() => setTableMode("table")} style={UI.pill(tableMode === "table", UI.purple)}>
                  Table (Purple)
                </div>
                <div role="button" onClick={() => setTableMode("header")} style={UI.pill(tableMode === "header", UI.orange)}>
                  Header (Orange)
                </div>
              </div>

              <div style={{ display: "flex", gap: 10, marginBottom: 10 }}>
                <div role="button" onClick={() => setTableMode("anchor")} style={UI.pill(tableMode === "anchor", UI.blue)}>
                  Anchor (Blue)
                </div>
                <div role="button" onClick={() => setTableMode("column")} style={UI.pill(tableMode === "column", UI.teal)}>
                  Column (Teal)
                </div>
              </div>

              {tableMode === "anchor" && (
                <div style={{ marginTop: 6 }}>
                  <div style={UI.label}>Which Anchor?</div>
                  <select value={selectedTableAnchorKey} onChange={(e) => setSelectedTableAnchorKey(e.target.value)} style={UI.select}>
                    {TABLE_ANCHORS.map((a) => (
                      <option key={a.key} value={a.key}>
                        {a.expected_text}
                      </option>
                    ))}
                  </select>
                  <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
                    Draw a small box tightly around the printed header word(s).
                  </div>
                </div>
              )}

              {tableMode === "column" && (
                <div style={{ marginTop: 6 }}>
                  <div style={UI.label}>Which Column?</div>
                  <select value={selectedColumnKey} onChange={(e) => setSelectedColumnKey(e.target.value)} style={UI.select}>
                    {TABLE_COLUMNS.map((c) => (
                      <option key={c.key} value={c.key}>
                        {c.label}
                      </option>
                    ))}
                  </select>
                  <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
                    Columns should be drawn inside the table region.
                  </div>
                </div>
              )}
            </>
          )}

          <div style={{ fontSize: 12, color: UI.subtle, marginTop: 10 }}>
            Active: <b style={{ color: "#fff" }}>{activeModeLabel}</b>
          </div>
          <div style={{ fontSize: 12, color: UI.subtle, marginTop: 6 }}>
            Drag on the PDF to place this region. (Hold Space to pan)
          </div>
        </div>

        {/* Clear buttons */}
        <div style={{ display: "flex", gap: 10, marginBottom: 14 }}>
          {!selectedIsTable ? (
            <>
              <button onClick={() => clearCurrent("anchor")} style={{ ...UI.btnBase, ...UI.gray }}>
                Clear Anchor
              </button>
              <button onClick={() => clearCurrent("value")} style={{ ...UI.btnBase, ...UI.gray }}>
                Clear Value
              </button>
            </>
          ) : (
            <>
              <button onClick={() => clearCurrent(tableMode)} style={{ ...UI.btnBase, ...UI.gray }}>
                Clear Current ({tableMode})
              </button>
              <button onClick={() => clearCurrent("table")} style={{ ...UI.btnBase, ...UI.gray }}>
                Clear Table
              </button>
            </>
          )}
        </div>

        {/* SAVE */}
        <button
          onClick={saveConfig}
          disabled={!pdfUrl || sendStatus.state === "sending"}
          style={{
            ...UI.btnBase,
            ...(pdfUrl ? UI.greenDark : { background: "rgba(255,255,255,0.10)", color: "#aaa" }),
            border: pdfUrl ? "1px solid rgba(22,163,74,0.55)" : "1px solid rgba(255,255,255,0.12)",
          }}
        >
          {sendStatus.state === "sending" ? "Saving..." : "Save Config"}
        </button>

        {sendStatus.state !== "idle" && (
          <div
            style={{
              marginTop: 10,
              fontSize: 12,
              color: sendStatus.state === "ok" ? "#86efac" : sendStatus.state === "err" ? "#fecaca" : UI.subtle,
            }}
          >
            {sendStatus.msg}
          </div>
        )}

        <hr style={{ margin: "16px 0", borderColor: UI.border }} />

        <div style={{ display: "flex", gap: 10, marginBottom: 12 }}>
          <button
            type="button"
            onClick={() => setShowPreview((v) => !v)}
            style={{ ...UI.btnBase, background: "#0f172a", color: "#fff" }}
          >
            {showPreview ? "Hide Config Preview" : "Show Config Preview"}
          </button>
        </div>

        {showPreview && (
          <div style={{ marginTop: 14 }}>
            <div style={{ fontWeight: 900, marginBottom: 8 }}>Config Preview</div>
            <pre
              style={{
                margin: 0,
                padding: 12,
                borderRadius: 12,
                background: "#0b0f14",
                border: "1px solid rgba(255,255,255,0.10)",
                color: "#d1d5db",
                fontSize: 11,
                lineHeight: 1.35,
                whiteSpace: "pre-wrap",
                wordBreak: "break-word",
                maxHeight: 260,
                overflow: "auto",
              }}
            >
              {previewConfig ? JSON.stringify(previewConfig, null, 2) : "PDF not loaded yet..."}
            </pre>
          </div>
        )}
      </div>

      {/* Middle panel: PDF + overlay */}
      <div style={{ padding: 16, overflow: "auto", background: "#111" }}>
        {!pdfUrl ? (
          <div style={{ color: "#999", lineHeight: 1.4 }}>
            No PDF loaded.
            <br />
            Open using pipeline link:
            <br />
            <code style={{ color: "#ddd" }}>...?pdf_id=xxxx&template_id=T1_...</code>
          </div>
        ) : (
          <div
            style={{
              position: "relative",
              width: "fit-content",
              background: "#0b0b0b",
              border: `1px solid ${UI.border}`,
              borderRadius: 14,
              padding: 12,
            }}
          >
            <div
              ref={stageRef}
              style={{
                position: "relative",
                width: pageSize.w ? pageSize.w : "fit-content",
                transform: `translate(${pan.x}px, ${pan.y}px) scale(${scale})`,
                transformOrigin: "top left",
              }}
            >
              <Document
                file={pdfUrl}
                loading="Loading PDF..."
                onLoadError={(err) => {
                  console.error("PDF load error:", err);
                  alert(err.message);
                }}
              >
                <Page
                  pageNumber={1}
                  renderTextLayer={false}
                  renderAnnotationLayer={false}
                  onRenderSuccess={(page) => setPageSize({ w: page.width, h: page.height })}
                />
              </Document>

              {pageSize.w > 0 && pageSize.h > 0 && (
                <div
                  ref={overlayRef}
                  style={{
                    position: "absolute",
                    left: 0,
                    top: 0,
                    width: pageSize.w,
                    height: pageSize.h,
                    cursor: spaceDown ? (isPanning ? "grabbing" : "grab") : "crosshair",
                  }}
                  onMouseDown={onMouseDown}
                  onMouseMove={onMouseMove}
                  onMouseUp={onMouseUp}
                  onMouseLeave={() => {
                    onMouseUp();
                    setIsPanning(false);
                    panStartRef.current = null;
                  }}
                >
                  <svg width={pageSize.w} height={pageSize.h}>
                    {FIELDS.map((f) => {
                      const st = boxes[f.fieldId];

                      if (st?.kind === "scalar") {
                        const vDisp = getScalarDisplayValueBox(f.fieldId);
                        return (
                          <g key={f.fieldId}>
                            {st.anchor && (
                              <rect x={st.anchor.x} y={st.anchor.y} width={st.anchor.w} height={st.anchor.h} fill="none" stroke="#2563eb" strokeWidth="3" />
                            )}
                            {vDisp && (
                              <rect x={vDisp.x} y={vDisp.y} width={vDisp.w} height={vDisp.h} fill="none" stroke="#22c55e" strokeWidth="3" />
                            )}
                          </g>
                        );
                      }

                      if (st?.kind === "table") {
                        return (
                          <g key={f.fieldId}>
                            {st.tableAbs && (
                              <rect x={st.tableAbs.x} y={st.tableAbs.y} width={st.tableAbs.w} height={st.tableAbs.h} fill="none" stroke="#7c3aed" strokeWidth="3" />
                            )}
                            {st.headerAbs && (
                              <rect x={st.headerAbs.x} y={st.headerAbs.y} width={st.headerAbs.w} height={st.headerAbs.h} fill="none" stroke="#f59e0b" strokeWidth="3" />
                            )}

                            {TABLE_ANCHORS.map((a) => {
                              const b = st.anchorsAbs[a.key];
                              return (
                                b && <rect key={`a-${a.key}`} x={b.x} y={b.y} width={b.w} height={b.h} fill="none" stroke="#2563eb" strokeWidth="3" />
                              );
                            })}

                            {TABLE_COLUMNS.map((c) => {
                              const b = st.columnsAbs[c.key];
                              return (
                                b && <rect key={`c-${c.key}`} x={b.x} y={b.y} width={b.w} height={b.h} fill="none" stroke="#14b8a6" strokeWidth="3" />
                              );
                            })}
                          </g>
                        );
                      }

                      return null;
                    })}

                    {draft && !isPanning && (
                      <rect
                        x={draft.x}
                        y={draft.y}
                        width={draft.w}
                        height={draft.h}
                        fill="none"
                        stroke={
                          selectedIsTable
                            ? tableMode === "table"
                              ? "#7c3aed"
                              : tableMode === "header"
                              ? "#f59e0b"
                              : tableMode === "anchor"
                              ? "#2563eb"
                              : "#14b8a6"
                            : scalarMode === "anchor"
                            ? "#2563eb"
                            : "#22c55e"
                        }
                        strokeWidth="3"
                        strokeDasharray="6 4"
                      />
                    )}
                  </svg>
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      {/* Right panel */}
      <div
        style={{
          padding: 16,
          overflow: "auto",
          background: "#0b0f14",
          borderLeft: `1px solid ${UI.border}`,
          color: "#e5e7eb",
        }}
      >
        <h3 style={{ margin: "0 0 10px", fontSize: 18 }}>Config Preview</h3>
        <div style={{ fontSize: 12, color: "#9aa4b2", marginBottom: 10 }}>
          Live preview of what will be saved.
        </div>

        <pre
          style={{
            margin: 0,
            padding: 12,
            borderRadius: 12,
            background: "#05070a",
            border: "1px solid #1f2937",
            color: "#d1d5db",
            fontSize: 12,
            lineHeight: 1.35,
            whiteSpace: "pre-wrap",
            wordBreak: "break-word",
          }}
        >
          {previewConfig ? JSON.stringify(previewConfig, null, 2) : "PDF not loaded yet..."}
        </pre>
      </div>
    </div>
  );
}
