"use client";

import { DragEvent, KeyboardEvent, useEffect, useMemo, useRef, useState } from "react";
import {
  createCircuit,
  createCircuitDeviceRow,
  deleteCircuitById,
  deleteCircuitDeviceRowById,
  getCircuitTree,
  getNextCircuitIdentifier,
  listProjectDevices,
  moveCircuitDeviceRowById,
  reorderSectionCircuits,
  renumberCircuitSection,
  updateCircuitById,
  updateCircuitDeviceRowById,
} from "../utils/api";
import type {
  CircuitTreeCircuitDto,
  CircuitTreeDeviceRowDto,
  CircuitTreeResponseDto,
  ProjectDeviceDto,
} from "../types";

type CellKey =
  | "equipmentIdentifier"
  | "displayName"
  | "quantity"
  | "powerPerUnit"
  | "simultaneityFactor"
  | "rowTotalPower"
  | "circuitTotalPower"
  | "protectionSummary"
  | "cableSummary"
  | "roomSummary"
  | "remark";

type SaveDirection = "stay" | "next" | "prev";
type StartEditMode = "selectExisting" | "replaceWithTypedChar";
type RowType = "section" | "circuitCompact" | "circuitSummary" | "deviceRow" | "reserveCircuit" | "placeholder";
type CellKind = "circuitField" | "deviceField" | "computed" | "readonly";

interface SelectedCell {
  rowKey: string;
  cellKey: CellKey;
}

interface EditingCell extends SelectedCell {
  draft: string;
  mode: StartEditMode;
  focusToken: number;
}

interface SelectionIntent {
  rowKey: string;
  cellKey: CellKey;
  rowType: RowType;
  sectionId: string;
  circuitId?: string;
  deviceId?: string;
}

interface VisibleGridCell {
  cellKey: CellKey;
  editable: boolean;
  kind: CellKind;
  value: string | number | boolean | undefined;
}

interface VisibleGridRow {
  rowKey: string;
  rowType: RowType;
  sectionId: string;
  circuit?: CircuitTreeCircuitDto;
  device?: CircuitTreeDeviceRowDto;
  cells: VisibleGridCell[];
}

type ProjectDeviceDropIntent =
  | { kind: "new-circuit"; sectionId: string }
  | { kind: "add-to-circuit"; circuitId: string; sectionId: string };

type DeviceRowMoveDropIntent =
  | { kind: "move-to-circuit"; circuitId: string; sectionId: string }
  | { kind: "move-to-new-circuit"; sectionId: string };

type CircuitReorderDropIntent =
  | { kind: "before-circuit"; sectionId: string; targetCircuitId: string; valid: boolean }
  | { kind: "after-circuit"; sectionId: string; targetCircuitId: string; valid: boolean }
  | { kind: "section-end"; sectionId: string; valid: boolean };

const columns: Array<{ key: CellKey; label: string; numeric?: boolean }> = [
  { key: "equipmentIdentifier", label: "Equipment identifier" },
  { key: "displayName", label: "Display name" },
  { key: "quantity", label: "Quantity", numeric: true },
  { key: "powerPerUnit", label: "Power / unit", numeric: true },
  { key: "simultaneityFactor", label: "Simultaneity", numeric: true },
  { key: "rowTotalPower", label: "Row total", numeric: true },
  { key: "circuitTotalPower", label: "Circuit total", numeric: true },
  { key: "protectionSummary", label: "Protection summary" },
  { key: "cableSummary", label: "Cable summary" },
  { key: "roomSummary", label: "Room" },
  { key: "remark", label: "Remark" },
];

const deviceFieldKeys = new Set<CellKey>([
  "displayName",
  "roomSummary",
  "quantity",
  "powerPerUnit",
  "simultaneityFactor",
  "remark",
]);

const circuitFieldKeys = new Set<CellKey>([
  "equipmentIdentifier",
  "displayName",
  "protectionSummary",
  "cableSummary",
  "remark",
]);

function formatValue(value: string | number | boolean | undefined) {
  if (value === undefined || value === null || value === "") {
    return "-";
  }
  if (typeof value === "boolean") {
    return value ? "Yes" : "No";
  }
  return String(value);
}

function normalizeUiError(err: unknown): string {
  const message = err instanceof Error ? err.message : "Operation failed.";
  try {
    const parsed = JSON.parse(message) as { error?: string };
    if (parsed.error?.includes("Duplicate equipmentIdentifier")) {
      return "Das Betriebsmittelkennzeichen ist in dieser Stromkreisliste bereits vorhanden.";
    }
    if (parsed.error) {
      return parsed.error;
    }
  } catch {
    // ignore
  }
  if (message.includes("Duplicate equipmentIdentifier")) {
    return "Das Betriebsmittelkennzeichen ist in dieser Stromkreisliste bereits vorhanden.";
  }
  if (message.includes("Invalid number")) {
    return "Bitte einen gültigen Zahlenwert eingeben.";
  }
  return message;
}

function parseNumeric(cellKey: CellKey, draft: string): number | undefined {
  const trimmed = draft.trim();
  if (trimmed === "") {
    return undefined;
  }
  const parsed = Number(trimmed);
  if (Number.isNaN(parsed)) {
    throw new Error(`Invalid number in ${cellKey}`);
  }
  return parsed;
}

function getDeviceValue(device: CircuitTreeDeviceRowDto, key: CellKey): string | number | boolean | undefined {
  switch (key) {
    case "displayName":
      return device.displayName || device.name;
    case "roomSummary":
      return [device.roomNumberSnapshot, device.roomNameSnapshot].filter(Boolean).join(" ").trim() || undefined;
    case "quantity":
      return device.quantity;
    case "powerPerUnit":
      return device.powerPerUnit;
    case "simultaneityFactor":
      return device.simultaneityFactor;
    case "rowTotalPower":
      return device.rowTotalPower;
    case "remark":
      return device.remark;
    default:
      return undefined;
  }
}

function getCircuitValue(circuit: CircuitTreeCircuitDto, key: CellKey): string | number | boolean | undefined {
  switch (key) {
    case "equipmentIdentifier":
      return circuit.equipmentIdentifier;
    case "displayName":
      return circuit.displayName;
    case "circuitTotalPower":
      return circuit.circuitTotalPower;
    case "protectionSummary": {
      const current =
        circuit.protectionRatedCurrent !== undefined && circuit.protectionRatedCurrent !== null
          ? `${circuit.protectionRatedCurrent}A`
          : "";
      return [circuit.protectionType, current, circuit.protectionCharacteristic]
        .filter(Boolean)
        .join(" ")
        .trim() || undefined;
    }
    case "cableSummary": {
      const length =
        circuit.cableLength !== undefined && circuit.cableLength !== null ? `${circuit.cableLength} m` : "";
      return [circuit.cableType, circuit.cableCrossSection, length].filter(Boolean).join(", ").trim() || undefined;
    }
    case "remark":
      return circuit.remark;
    default:
      return undefined;
  }
}

function getCellKind(rowType: RowType, key: CellKey): CellKind {
  if (key === "rowTotalPower" || key === "circuitTotalPower") {
    return "computed";
  }
  if (rowType === "section") {
    return "readonly";
  }
  if (rowType === "placeholder") {
    if (deviceFieldKeys.has(key)) {
      return "deviceField";
    }
    if (circuitFieldKeys.has(key)) {
      return "circuitField";
    }
    return "readonly";
  }
  if (rowType === "deviceRow") {
    return deviceFieldKeys.has(key) ? "deviceField" : "readonly";
  }
  if (rowType === "circuitSummary") {
    return circuitFieldKeys.has(key) ? "circuitField" : "readonly";
  }
  if (rowType === "reserveCircuit") {
    if (deviceFieldKeys.has(key)) {
      return "deviceField";
    }
    if (circuitFieldKeys.has(key)) {
      return "circuitField";
    }
    return "readonly";
  }
  if (rowType === "circuitCompact") {
    if (deviceFieldKeys.has(key)) {
      return "deviceField";
    }
    if (circuitFieldKeys.has(key)) {
      return "circuitField";
    }
    return "readonly";
  }
  return "readonly";
}

function isPrintableKey(event: KeyboardEvent<HTMLElement>) {
  return event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey;
}

export function CircuitTreeEditor(props: { projectId: string; circuitListId: string }) {
  const { projectId, circuitListId } = props;
  const [data, setData] = useState<CircuitTreeResponseDto | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [selectedCell, setSelectedCell] = useState<SelectedCell | null>(null);
  const [editingCell, setEditingCell] = useState<EditingCell | null>(null);
  const [activeSectionId, setActiveSectionId] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [projectDevices, setProjectDevices] = useState<ProjectDeviceDto[]>([]);
  const [projectDeviceSearch, setProjectDeviceSearch] = useState("");
  const [selectedProjectDeviceId, setSelectedProjectDeviceId] = useState<string | null>(null);
  const [targetSectionId, setTargetSectionId] = useState<string | null>(null);
  const [targetCircuitId, setTargetCircuitId] = useState<string | null>(null);
  const [draggingProjectDeviceId, setDraggingProjectDeviceId] = useState<string | null>(null);
  const [dropIntent, setDropIntent] = useState<ProjectDeviceDropIntent | null>(null);
  const [draggingDeviceRowId, setDraggingDeviceRowId] = useState<string | null>(null);
  const [deviceMoveIntent, setDeviceMoveIntent] = useState<DeviceRowMoveDropIntent | null>(null);
  const [draggingCircuitId, setDraggingCircuitId] = useState<string | null>(null);
  const [circuitReorderIntent, setCircuitReorderIntent] = useState<CircuitReorderDropIntent | null>(null);
  const [pendingFocus, setPendingFocus] = useState<SelectedCell | null>(null);
  const pendingSelectionAfterReload = useRef<SelectionIntent | null>(null);
  const containerRef = useRef<HTMLDivElement | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const focusTokenRef = useRef(1);

  async function loadTree(options?: { showLoading?: boolean }) {
    const showLoading = options?.showLoading ?? false;
    if (showLoading) {
      setIsLoading(true);
    }
    setError(null);
    try {
      const tree = await getCircuitTree(projectId, circuitListId);
      setData(tree);
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      if (showLoading) {
        setIsLoading(false);
      }
    }
  }

  useEffect(() => {
    void loadTree({ showLoading: true });
  }, [projectId, circuitListId]);

  useEffect(() => {
    async function loadProjectDeviceList() {
      try {
        const list = await listProjectDevices(projectId);
        setProjectDevices(list);
      } catch (err) {
        setError(normalizeUiError(err));
      }
    }
    void loadProjectDeviceList();
  }, [projectId]);

  const visibleRows = useMemo(() => {
    if (!data) {
      return [] as VisibleGridRow[];
    }
    const rows: VisibleGridRow[] = [];
    for (const section of data.sections) {
      rows.push({
        rowKey: `section:${section.id}`,
        rowType: "section",
        sectionId: section.id,
        cells: columns.map((col) => ({ cellKey: col.key, editable: false, kind: "readonly", value: undefined })),
      });
      for (const circuit of section.circuits) {
        if (circuit.deviceRows.length === 0) {
          rows.push(makeRow("reserveCircuit", section.id, circuit));
          continue;
        }
        if (circuit.deviceRows.length === 1) {
          rows.push(makeRow("circuitCompact", section.id, circuit, circuit.deviceRows[0]));
          continue;
        }
        rows.push(makeRow("circuitSummary", section.id, circuit));
        for (const device of circuit.deviceRows) {
          rows.push(makeRow("deviceRow", section.id, circuit, device));
        }
      }
      rows.push(makeRow("placeholder", section.id));
    }
    return rows;
  }, [data]);

  const searchableProjectDevices = useMemo(() => {
    const term = projectDeviceSearch.trim().toLowerCase();
    if (!term) {
      return projectDevices;
    }
    return projectDevices.filter((device) => {
      const haystack = `${device.name} ${device.displayName}`.toLowerCase();
      return haystack.includes(term);
    });
  }, [projectDeviceSearch, projectDevices]);

  const circuitOptions = useMemo(() => {
    if (!data) {
      return [] as Array<{ id: string; label: string; sectionId: string }>;
    }
    return data.sections.flatMap((section) =>
      section.circuits.map((circuit) => ({
        id: circuit.id,
        sectionId: section.id,
        label: `${circuit.equipmentIdentifier} - ${circuit.displayName || "Circuit"}`,
      }))
    );
  }, [data]);

  function makeRow(
    rowType: RowType,
    sectionId: string,
    circuit?: CircuitTreeCircuitDto,
    device?: CircuitTreeDeviceRowDto
  ): VisibleGridRow {
    const rowKey =
      rowType === "placeholder"
        ? `placeholder:${sectionId}`
        : rowType === "deviceRow" && device
          ? `device:${device.id}`
          : `${rowType}:${circuit?.id ?? sectionId}`;
    const cells = columns.map((col) => {
      const kind = getCellKind(rowType, col.key);
      const editable = kind === "circuitField" || kind === "deviceField";
      let value: string | number | boolean | undefined;
      if (rowType === "placeholder") {
        value = col.key === "equipmentIdentifier" ? "-frei-" : undefined;
      } else if (kind === "deviceField" && device) {
        value = getDeviceValue(device, col.key);
      } else if (kind === "circuitField" && circuit) {
        value = getCircuitValue(circuit, col.key);
      } else if (col.key === "circuitTotalPower" && circuit) {
        value = circuit.circuitTotalPower;
      } else if (col.key === "rowTotalPower" && device) {
        value = device.rowTotalPower;
      }
      return { cellKey: col.key, editable, kind, value };
    });
    return { rowKey, rowType, sectionId, circuit, device, cells };
  }

  const editableCells = useMemo(
    () =>
      visibleRows.flatMap((row) =>
        row.cells
          .filter((cell) => cell.editable)
          .map((cell) => ({ rowKey: row.rowKey, cellKey: cell.cellKey as CellKey }))
      ),
    [visibleRows]
  );

  const rowCellMap = useMemo(() => {
    const map = new Map<string, CellKey[]>();
    for (const row of visibleRows) {
      const keys = row.cells.filter((cell) => cell.editable).map((cell) => cell.cellKey as CellKey);
      if (keys.length) {
        map.set(row.rowKey, keys);
      }
    }
    return map;
  }, [visibleRows]);

  const editableRowOrder = useMemo(
    () => visibleRows.filter((row) => rowCellMap.has(row.rowKey)).map((row) => row.rowKey),
    [visibleRows, rowCellMap]
  );

  useEffect(() => {
    if (!selectedCell && editableCells.length > 0) {
      setSelectedCell(editableCells[0]);
      return;
    }
    if (selectedCell) {
      const valid = editableCells.some(
        (cell) => cell.rowKey === selectedCell.rowKey && cell.cellKey === selectedCell.cellKey
      );
      if (!valid) {
        setSelectedCell(editableCells[0] ?? null);
      }
    }
  }, [editableCells, selectedCell]);

  function buildSelectionIntent(cell: SelectedCell): SelectionIntent | null {
    const row = findRow(cell.rowKey);
    if (!row) {
      return null;
    }
    return {
      rowKey: cell.rowKey,
      cellKey: cell.cellKey,
      rowType: row.rowType,
      sectionId: row.sectionId,
      circuitId: row.circuit?.id,
      deviceId: row.device?.id,
    };
  }

  function resolveSelectionIntent(intent: SelectionIntent): SelectedCell | null {
    const direct = editableCells.find(
      (cell) => cell.rowKey === intent.rowKey && cell.cellKey === intent.cellKey
    );
    if (direct) {
      return direct;
    }

    const rowById = visibleRows.find((row) => {
      if (intent.deviceId && row.device?.id === intent.deviceId) {
        return true;
      }
      if (intent.circuitId && row.circuit?.id === intent.circuitId && row.rowType === intent.rowType) {
        return true;
      }
      return false;
    });
    if (rowById) {
      const rowCells = rowCellMap.get(rowById.rowKey) ?? [];
      if (rowCells.includes(intent.cellKey)) {
        return { rowKey: rowById.rowKey, cellKey: intent.cellKey };
      }
      if (rowCells.length > 0) {
        return { rowKey: rowById.rowKey, cellKey: rowCells[0] };
      }
    }

    const inSameCircuit = visibleRows.find((row) => intent.circuitId && row.circuit?.id === intent.circuitId);
    if (inSameCircuit) {
      const cells = rowCellMap.get(inSameCircuit.rowKey) ?? [];
      if (cells.length > 0) {
        return { rowKey: inSameCircuit.rowKey, cellKey: cells[0] };
      }
    }

    const inSameSection = visibleRows.find((row) => row.sectionId === intent.sectionId && rowCellMap.has(row.rowKey));
    if (inSameSection) {
      const cells = rowCellMap.get(inSameSection.rowKey) ?? [];
      if (cells.length > 0) {
        return { rowKey: inSameSection.rowKey, cellKey: cells[0] };
      }
    }

    return editableCells[0] ?? null;
  }

  useEffect(() => {
    const intent = pendingSelectionAfterReload.current;
    if (!intent || !data) {
      return;
    }
    const resolved = resolveSelectionIntent(intent);
    pendingSelectionAfterReload.current = null;
    if (resolved) {
      setSelectedCell(resolved);
    }
    requestAnimationFrame(() => containerRef.current?.focus());
  }, [data, editableCells, visibleRows]);

  useEffect(() => {
    if (!pendingFocus) {
      return;
    }
    setSelectedCell(pendingFocus);
    startEdit(pendingFocus, "selectExisting");
    setPendingFocus(null);
  }, [pendingFocus]);

  useEffect(() => {
    if (!editingCell) {
      return;
    }
    requestAnimationFrame(() => {
      if (!inputRef.current) {
        return;
      }
      inputRef.current.focus();
      if (editingCell.mode === "selectExisting") {
        inputRef.current.select();
      } else {
        const len = inputRef.current.value.length;
        inputRef.current.setSelectionRange(len, len);
      }
    });
  }, [editingCell?.focusToken]);

  function findRow(rowKey: string) {
    return visibleRows.find((row) => row.rowKey === rowKey);
  }

  function findCell(rowKey: string, cellKey: CellKey) {
    const row = findRow(rowKey);
    return row?.cells.find((cell) => cell.cellKey === cellKey);
  }

  function startEdit(cell: SelectedCell, mode: StartEditMode, typedChar?: string) {
    const visibleCell = findCell(cell.rowKey, cell.cellKey);
    if (!visibleCell || !visibleCell.editable) {
      return;
    }
    const currentDisplay = mode === "replaceWithTypedChar" ? typedChar ?? "" : String(visibleCell.value ?? "");
    focusTokenRef.current += 1;
    setEditingCell({
      ...cell,
      mode,
      draft: currentDisplay === "-" ? "" : currentDisplay,
      focusToken: focusTokenRef.current,
    });
  }

  function moveHorizontal(direction: 1 | -1) {
    if (!selectedCell) {
      return;
    }
    const rowCells = rowCellMap.get(selectedCell.rowKey) ?? [];
    const idx = rowCells.indexOf(selectedCell.cellKey);
    if (idx < 0) {
      return;
    }
    const next = rowCells[Math.min(rowCells.length - 1, Math.max(0, idx + direction))];
    setSelectedCell({ rowKey: selectedCell.rowKey, cellKey: next });
  }

  function moveVertical(direction: 1 | -1) {
    if (!selectedCell) {
      return;
    }
    const rowIndex = editableRowOrder.indexOf(selectedCell.rowKey);
    if (rowIndex < 0) {
      return;
    }
    const targetIndex = rowIndex + direction;
    if (targetIndex < 0 || targetIndex >= editableRowOrder.length) {
      return;
    }
    const targetRowKey = editableRowOrder[targetIndex];
    const targetCells = rowCellMap.get(targetRowKey) ?? [];
    if (!targetCells.length) {
      return;
    }
    const preferred = columns.findIndex((col) => col.key === selectedCell.cellKey);
    let best = targetCells[0];
    let bestDistance = Number.POSITIVE_INFINITY;
    for (const key of targetCells) {
      const idx = columns.findIndex((col) => col.key === key);
      const dist = Math.abs(idx - preferred);
      if (dist < bestDistance) {
        bestDistance = dist;
        best = key;
      }
    }
    setSelectedCell({ rowKey: targetRowKey, cellKey: best });
  }

  async function patchCircuit(circuitId: string, key: CellKey, draft: string) {
    const payload: Record<string, unknown> = {};
    if (key === "protectionSummary" || key === "cableSummary") {
      payload.remark = draft.trim() === "" ? undefined : draft;
    } else {
      payload[key] = draft.trim() === "" ? undefined : draft;
    }
    await updateCircuitById(circuitId, payload);
  }

  async function patchDeviceRow(rowId: string, key: CellKey, draft: string) {
    const payload: Record<string, unknown> = {};
    if (["quantity", "powerPerUnit", "simultaneityFactor"].includes(key)) {
      payload[key] = parseNumeric(key, draft);
    } else if (key === "roomSummary") {
      const trimmed = draft.trim();
      if (!trimmed) {
        payload.roomNumberSnapshot = undefined;
        payload.roomNameSnapshot = undefined;
      } else {
        const firstSpace = trimmed.indexOf(" ");
        if (firstSpace > 0) {
          payload.roomNumberSnapshot = trimmed.slice(0, firstSpace).trim();
          payload.roomNameSnapshot = trimmed.slice(firstSpace + 1).trim();
        } else {
          payload.roomNumberSnapshot = trimmed;
          payload.roomNameSnapshot = undefined;
        }
      }
    } else {
      payload[key] = draft.trim() === "" ? undefined : draft;
    }
    await updateCircuitDeviceRowById(rowId, payload);
  }

  async function createFromPlaceholder(
    sectionId: string,
    key: CellKey,
    draft: string
  ): Promise<SelectedCell> {
    const section = data?.sections.find((entry) => entry.id === sectionId);
    if (!section) {
      throw new Error("Section not found.");
    }
    const next = await getNextCircuitIdentifier(sectionId);
    const sortOrder =
      section.circuits.length > 0 ? Math.max(...section.circuits.map((circuit) => circuit.sortOrder)) + 10 : 10;
    const isDeviceField = deviceFieldKeys.has(key);
    const createdCircuit = (await createCircuit(projectId, circuitListId, {
      sectionId,
      equipmentIdentifier: next.nextIdentifier,
      displayName: "New circuit",
      sortOrder,
      isReserve: !isDeviceField,
    })) as CircuitTreeCircuitDto;

    if (isDeviceField) {
      const createdRow = (await createCircuitDeviceRow(createdCircuit.id, {
        name: "Manual device",
        displayName: "Manual device",
        phaseType: "single_phase",
        quantity: 1,
        powerPerUnit: 0,
        simultaneityFactor: 1,
        cosPhi: 1,
      })) as { id: string };
      await patchDeviceRow(createdRow.id, key, draft);
      return { rowKey: `circuitCompact:${createdCircuit.id}`, cellKey: key };
    }

    await patchCircuit(createdCircuit.id, key, draft);
    return { rowKey: `reserveCircuit:${createdCircuit.id}`, cellKey: key };
  }

  async function commitEdit(direction: SaveDirection = "stay") {
    if (!editingCell) {
      return;
    }
    const row = findRow(editingCell.rowKey);
    const cell = row?.cells.find((entry) => entry.cellKey === editingCell.cellKey);
    if (!row || !cell || !cell.editable) {
      setEditingCell(null);
      return;
    }

    try {
      setIsSaving(true);
      setError(null);
      let targetSelection: SelectedCell = { rowKey: editingCell.rowKey, cellKey: editingCell.cellKey };

      if (row.rowType === "placeholder") {
        targetSelection = await createFromPlaceholder(row.sectionId, editingCell.cellKey, editingCell.draft);
      } else if (cell.kind === "circuitField" && row.circuit) {
        await patchCircuit(row.circuit.id, editingCell.cellKey, editingCell.draft);
      } else if (cell.kind === "deviceField") {
        if (row.device) {
          await patchDeviceRow(row.device.id, editingCell.cellKey, editingCell.draft);
        } else if (row.rowType === "reserveCircuit" && row.circuit) {
          const created = (await createCircuitDeviceRow(row.circuit.id, {
            name: "Reserve load",
            displayName: "Reserve load",
            phaseType: "single_phase",
            quantity: 1,
            powerPerUnit: 0,
            simultaneityFactor: 1,
            cosPhi: 1,
          })) as { id: string };
          await patchDeviceRow(created.id, editingCell.cellKey, editingCell.draft);
          targetSelection = { rowKey: `circuitCompact:${row.circuit.id}`, cellKey: editingCell.cellKey };
        }
      }

      if (direction !== "stay") {
        const idx = editableCells.findIndex(
          (entry) => entry.rowKey === targetSelection.rowKey && entry.cellKey === targetSelection.cellKey
        );
        if (idx >= 0) {
          const targetIdx =
            direction === "next"
              ? Math.min(editableCells.length - 1, idx + 1)
              : Math.max(0, idx - 1);
          targetSelection = editableCells[targetIdx];
        }
      }

      const intent = buildSelectionIntent(targetSelection);
      setEditingCell(null);
      if (intent) {
        pendingSelectionAfterReload.current = intent;
      }
      await loadTree({ showLoading: false });
      if (!intent) {
        requestAnimationFrame(() => containerRef.current?.focus());
      }
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  function cancelEdit() {
    if (!editingCell) {
      return;
    }
    setEditingCell(null);
    setSelectedCell({ rowKey: editingCell.rowKey, cellKey: editingCell.cellKey });
    requestAnimationFrame(() => containerRef.current?.focus());
  }

  async function handleAddReserveCircuit(sectionId: string) {
    try {
      setError(null);
      setIsSaving(true);
      const section = data?.sections.find((entry) => entry.id === sectionId);
      if (!section) {
        return;
      }
      const next = await getNextCircuitIdentifier(sectionId);
      const sortOrder =
        section.circuits.length > 0 ? Math.max(...section.circuits.map((circuit) => circuit.sortOrder)) + 10 : 10;
      await createCircuit(projectId, circuitListId, {
        sectionId,
        equipmentIdentifier: next.nextIdentifier,
        displayName: "Reserve",
        sortOrder,
        isReserve: true,
      });
      await loadTree({ showLoading: false });
      setActiveSectionId(sectionId);
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleAddManualDevice(circuit: CircuitTreeCircuitDto, sectionId: string) {
    try {
      setError(null);
      setIsSaving(true);
      const created = (await createCircuitDeviceRow(circuit.id, {
        name: "Manual device",
        displayName: "Manual device",
        phaseType: "single_phase",
        quantity: 1,
        powerPerUnit: 0,
        simultaneityFactor: 1,
        cosPhi: 1,
      })) as { id: string };
      await loadTree({ showLoading: false });
      setActiveSectionId(sectionId);
      setPendingFocus({
        rowKey: circuit.deviceRows.length === 0 ? `circuitCompact:${circuit.id}` : `device:${created.id}`,
        cellKey: "displayName",
      });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  function resolvePhaseType(device: ProjectDeviceDto): string {
    if (device.phaseCount === 3) {
      return "three_phase";
    }
    return "single_phase";
  }

  function resolveSelectedProjectDevice() {
    if (!selectedProjectDeviceId) {
      return null;
    }
    return projectDevices.find((device) => device.id === selectedProjectDeviceId) ?? null;
  }

  async function handleAddProjectDeviceAsNewCircuit() {
    const device = resolveSelectedProjectDevice();
    if (!device) {
      setError("Please select a project device.");
      return;
    }
    if (!targetSectionId) {
      setError("Please select a target section.");
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      await insertProjectDeviceAsNewCircuit(device, targetSectionId);
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleAddProjectDeviceToCircuit() {
    const device = resolveSelectedProjectDevice();
    if (!device) {
      setError("Please select a project device.");
      return;
    }
    let circuitId = targetCircuitId;
    if (!circuitId && selectedCell) {
      const row = findRow(selectedCell.rowKey);
      if (row?.circuit?.id) {
        circuitId = row.circuit.id;
      }
    }
    if (!circuitId) {
      setError("Please select a target circuit.");
      return;
    }

    try {
      setError(null);
      setIsSaving(true);
      await insertProjectDeviceToCircuit(device, circuitId);
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function insertProjectDeviceAsNewCircuit(device: ProjectDeviceDto, sectionId: string) {
    const section = data?.sections.find((entry) => entry.id === sectionId);
    if (!section) {
      throw new Error("Invalid target section.");
    }
    const next = await getNextCircuitIdentifier(sectionId);
    const sortOrder =
      section.circuits.length > 0 ? Math.max(...section.circuits.map((circuit) => circuit.sortOrder)) + 10 : 10;
    const createdCircuit = (await createCircuit(projectId, circuitListId, {
      sectionId,
      equipmentIdentifier: next.nextIdentifier,
      displayName: device.displayName || device.name,
      sortOrder,
      isReserve: false,
    })) as CircuitTreeCircuitDto;

    const createdRow = (await createCircuitDeviceRow(createdCircuit.id, {
      linkedProjectDeviceId: device.id,
      name: device.name,
      displayName: device.displayName,
      phaseType: resolvePhaseType(device),
      quantity: device.quantity,
      powerPerUnit: device.installedPowerPerUnitKw,
      simultaneityFactor: device.demandFactor,
      cosPhi: device.powerFactor ?? undefined,
      category: device.category ?? undefined,
    })) as { id: string };

    await loadTree({ showLoading: false });
    setActiveSectionId(sectionId);
    setTargetCircuitId(createdCircuit.id);
    setPendingFocus({ rowKey: `device:${createdRow.id}`, cellKey: "displayName" });
  }

  async function insertProjectDeviceToCircuit(device: ProjectDeviceDto, circuitId: string) {
    const createdRow = (await createCircuitDeviceRow(circuitId, {
      linkedProjectDeviceId: device.id,
      name: device.name,
      displayName: device.displayName,
      phaseType: resolvePhaseType(device),
      quantity: device.quantity,
      powerPerUnit: device.installedPowerPerUnitKw,
      simultaneityFactor: device.demandFactor,
      cosPhi: device.powerFactor ?? undefined,
      category: device.category ?? undefined,
    })) as { id: string };
    await loadTree({ showLoading: false });
    setPendingFocus({ rowKey: `device:${createdRow.id}`, cellKey: "displayName" });
  }

  function parseDraggedProjectDeviceId(event: DragEvent<HTMLElement>) {
    return event.dataTransfer.getData("application/x-project-device-id") || null;
  }

  function parseDraggedDeviceRowId(event: DragEvent<HTMLElement>) {
    return event.dataTransfer.getData("application/x-circuit-device-row-id") || null;
  }

  function findDeviceRowCircuitId(deviceRowId: string) {
    for (const section of data?.sections ?? []) {
      for (const circuit of section.circuits) {
        if (circuit.deviceRows.some((row) => row.id === deviceRowId)) {
          return circuit.id;
        }
      }
    }
    return null;
  }

  function findCircuitSectionId(circuitId: string) {
    for (const section of data?.sections ?? []) {
      if (section.circuits.some((circuit) => circuit.id === circuitId)) {
        return section.id;
      }
    }
    return null;
  }

  async function applyCircuitReorder(intent: CircuitReorderDropIntent, sourceCircuitId: string) {
    const section = data?.sections.find((entry) => entry.id === intent.sectionId);
    if (!section) {
      throw new Error("Invalid section id.");
    }
    const ids = section.circuits.map((circuit) => circuit.id);
    const fromIndex = ids.indexOf(sourceCircuitId);
    if (fromIndex < 0) {
      throw new Error("Invalid source circuit.");
    }
    const nextIds = [...ids];
    nextIds.splice(fromIndex, 1);

    if (intent.kind === "section-end") {
      nextIds.push(sourceCircuitId);
    } else {
      const targetIndex = nextIds.indexOf(intent.targetCircuitId);
      if (targetIndex < 0) {
        throw new Error("Invalid target circuit.");
      }
      const insertIndex = intent.kind === "after-circuit" ? targetIndex + 1 : targetIndex;
      nextIds.splice(insertIndex, 0, sourceCircuitId);
    }
    await reorderSectionCircuits(section.id, nextIds);
  }

  async function handleDropWithIntent(event: DragEvent<HTMLElement>, intent: ProjectDeviceDropIntent) {
    event.preventDefault();
    event.stopPropagation();
    const draggedId = parseDraggedProjectDeviceId(event) ?? draggingProjectDeviceId;
    setDropIntent(null);
    setDraggingProjectDeviceId(null);
    if (!draggedId) {
      setError("Missing dragged project device.");
      return;
    }
    const device = projectDevices.find((entry) => entry.id === draggedId);
    if (!device) {
      setError("Invalid project device drop source.");
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      if (intent.kind === "new-circuit") {
        await insertProjectDeviceAsNewCircuit(device, intent.sectionId);
      } else {
        await insertProjectDeviceToCircuit(device, intent.circuitId);
      }
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDeviceRowDropWithIntent(event: DragEvent<HTMLElement>, intent: DeviceRowMoveDropIntent) {
    event.preventDefault();
    event.stopPropagation();
    const rowId = parseDraggedDeviceRowId(event) ?? draggingDeviceRowId;
    setDeviceMoveIntent(null);
    setDraggingDeviceRowId(null);
    if (!rowId) {
      setError("Missing dragged device row.");
      return;
    }

    const sourceCircuitId = findDeviceRowCircuitId(rowId);
    if (!sourceCircuitId) {
      setError("Invalid dragged device row.");
      return;
    }

    try {
      setError(null);
      setIsSaving(true);
      if (intent.kind === "move-to-circuit") {
        if (intent.circuitId === sourceCircuitId) {
          return;
        }
        await moveCircuitDeviceRowById(rowId, { targetCircuitId: intent.circuitId });
      } else {
        await moveCircuitDeviceRowById(rowId, {
          targetSectionId: intent.sectionId,
          createNewCircuit: true,
        });
      }
      await loadTree({ showLoading: false });
      setPendingFocus({ rowKey: `device:${rowId}`, cellKey: "displayName" });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleCircuitReorderDrop(event: DragEvent<HTMLElement>, intent: CircuitReorderDropIntent) {
    event.preventDefault();
    event.stopPropagation();
    const sourceCircuitId = event.dataTransfer.getData("application/x-circuit-id") || draggingCircuitId;
    setCircuitReorderIntent(null);
    setDraggingCircuitId(null);
    if (!sourceCircuitId) {
      setError("Missing dragged circuit.");
      return;
    }
    if (!intent.valid) {
      setError("Cross-section circuit move is not allowed in this phase.");
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      await applyCircuitReorder(intent, sourceCircuitId);
      pendingSelectionAfterReload.current = {
        rowKey: `circuitSummary:${sourceCircuitId}`,
        cellKey: "equipmentIdentifier",
        rowType: "circuitSummary",
        sectionId: intent.sectionId,
        circuitId: sourceCircuitId,
      };
      await loadTree({ showLoading: false });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDeleteDevice(rowId: string) {
    if (!confirm("Delete this device row?")) {
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      await deleteCircuitDeviceRowById(rowId);
      await loadTree({ showLoading: false });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDeleteCircuit(circuitId: string) {
    if (!confirm("Delete this circuit and all assigned device rows?")) {
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      await deleteCircuitById(circuitId);
      await loadTree({ showLoading: false });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleRenumberSection(sectionId: string) {
    if (!confirm("Renumber this section? Only circuits in this section will change.")) {
      return;
    }
    try {
      setError(null);
      setIsSaving(true);
      await renumberCircuitSection(sectionId);
      await loadTree({ showLoading: false });
    } catch (err) {
      setError(normalizeUiError(err));
    } finally {
      setIsSaving(false);
    }
  }

  function handleContainerFocus() {
    if (editingCell) {
      const row = findRow(editingCell.rowKey);
      const cell = row?.cells.find((entry) => entry.cellKey === editingCell.cellKey);
      if (!row || !cell || !cell.editable) {
        setEditingCell(null);
      }
      return;
    }
    if (!selectedCell && editableCells.length) {
      setSelectedCell(editableCells[0]);
    }
  }

  function handleContainerKeyDown(event: KeyboardEvent<HTMLDivElement>) {
    if (editingCell) {
      if (event.key === "Tab") {
        event.preventDefault();
      }
      return;
    }
    const isCtrlPlus =
      event.ctrlKey &&
      (event.key === "+" || (event.shiftKey && event.key === "=") || event.code === "NumpadAdd");
    if (isCtrlPlus) {
      event.preventDefault();
      const sectionId = activeSectionId ?? data?.sections[0]?.id;
      if (sectionId) {
        void handleAddReserveCircuit(sectionId);
      }
      return;
    }
    if (event.key === "Tab" && selectedCell) {
      event.preventDefault();
      const idx = editableCells.findIndex(
        (entry) => entry.rowKey === selectedCell.rowKey && entry.cellKey === selectedCell.cellKey
      );
      if (idx >= 0) {
        const nextIdx =
          event.shiftKey ? Math.max(0, idx - 1) : Math.min(editableCells.length - 1, idx + 1);
        setSelectedCell(editableCells[nextIdx]);
      }
      return;
    }
    if (event.key === "ArrowRight") {
      event.preventDefault();
      moveHorizontal(1);
      return;
    }
    if (event.key === "ArrowLeft") {
      event.preventDefault();
      moveHorizontal(-1);
      return;
    }
    if (event.key === "ArrowDown") {
      event.preventDefault();
      moveVertical(1);
      return;
    }
    if (event.key === "ArrowUp") {
      event.preventDefault();
      moveVertical(-1);
      return;
    }
    if ((event.key === "Enter" || event.key === "F2") && selectedCell) {
      event.preventDefault();
      startEdit(selectedCell, "selectExisting");
      return;
    }
    if (isPrintableKey(event) && selectedCell) {
      event.preventDefault();
      startEdit(selectedCell, "replaceWithTypedChar", event.key);
    }
  }

  if (isLoading && !data) {
    return <div className="notice info">Loading circuit tree editor...</div>;
  }
  if (error) {
    return <div className="notice error">{error}</div>;
  }
  if (!data || data.sections.length === 0) {
    return <div className="notice muted">No sections/circuits available.</div>;
  }

  return (
    <div className="tree-editor-shell">
      {isSaving ? <div className="notice info">Saving...</div> : null}
      <div className="tree-editor-layout">
        <aside className="project-device-sidebar">
          <h3>Project devices</h3>
          <input
            type="text"
            placeholder="Search name/displayName..."
            value={projectDeviceSearch}
            onChange={(event) => setProjectDeviceSearch(event.target.value)}
          />
          <div className="project-device-list">
            {searchableProjectDevices.map((device) => (
              <button
                key={device.id}
                type="button"
                className={`project-device-item ${selectedProjectDeviceId === device.id ? "selected" : ""} ${draggingProjectDeviceId === device.id ? "dragging" : ""}`}
                onClick={() => setSelectedProjectDeviceId(device.id)}
                draggable
                onDragStart={(event) => {
                  setSelectedProjectDeviceId(device.id);
                  setDraggingProjectDeviceId(device.id);
                  setDraggingDeviceRowId(null);
                  setDraggingCircuitId(null);
                  setDeviceMoveIntent(null);
                  setCircuitReorderIntent(null);
                  event.dataTransfer.effectAllowed = "copy";
                  event.dataTransfer.setData("application/x-project-device-id", device.id);
                }}
                onDragEnd={() => {
                  setDraggingProjectDeviceId(null);
                  setDropIntent(null);
                }}
              >
                <strong>{device.displayName || device.name}</strong>
                <span>Name: {device.name}</span>
                <span>Phase: {device.phaseCount === 3 ? "three_phase" : "single_phase"}</span>
                <span>Qty: {device.quantity}</span>
                <span>P/unit: {device.installedPowerPerUnitKw}</span>
                <span>g: {device.demandFactor}</span>
                <span>Cost group: -</span>
                <span>Category: {device.category || "-"}</span>
              </button>
            ))}
            {searchableProjectDevices.length === 0 ? <p className="notice muted">No matching project devices.</p> : null}
          </div>
          <div className="sidebar-actions">
            <label>
              Target section
              <select
                value={targetSectionId ?? ""}
                onChange={(event) => setTargetSectionId(event.target.value || null)}
              >
                <option value="">Select section...</option>
                {data.sections.map((section) => (
                  <option key={section.id} value={section.id}>
                    {section.displayName}
                  </option>
                ))}
              </select>
            </label>
            <button type="button" onClick={() => void handleAddProjectDeviceAsNewCircuit()}>
              Add as new circuit
            </button>
            <label>
              Target circuit
              <select
                value={targetCircuitId ?? ""}
                onChange={(event) => setTargetCircuitId(event.target.value || null)}
              >
                <option value="">Use selected row circuit...</option>
                {circuitOptions.map((option) => (
                  <option key={option.id} value={option.id}>
                    {option.label}
                  </option>
                ))}
              </select>
            </label>
            <button type="button" onClick={() => void handleAddProjectDeviceToCircuit()}>
              Add to selected circuit
            </button>
          </div>
        </aside>
        <div
          className="tree-grid-wrap"
          ref={containerRef}
          tabIndex={0}
          onFocus={handleContainerFocus}
          onKeyDown={handleContainerKeyDown}
        >
          <table className="tree-grid">
          <thead>
            <tr>
              {columns.map((column) => (
                <th key={column.key} className={column.numeric ? "num" : ""}>
                  {column.label}
                </th>
              ))}
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {visibleRows.map((row) => {
              if (row.rowType === "section") {
                const section = data.sections.find((entry) => entry.id === row.sectionId)!;
                return (
                  <tr
                    key={row.rowKey}
                    className={`section-row ${
                      dropIntent?.kind === "new-circuit" && dropIntent.sectionId === section.id ? "drop-target-active" : ""
                    }`}
                    onDragOver={(event) => {
                      if (draggingCircuitId) {
                        event.preventDefault();
                        event.dataTransfer.dropEffect = "none";
                        setCircuitReorderIntent({
                          kind: "section-end",
                          sectionId: section.id,
                          valid: false,
                        });
                        return;
                      }
                      if (!draggingProjectDeviceId) {
                        return;
                      }
                      event.preventDefault();
                      event.dataTransfer.dropEffect = "copy";
                      setDropIntent({ kind: "new-circuit", sectionId: section.id });
                    }}
                    onDragLeave={() => {
                      if (dropIntent?.kind === "new-circuit" && dropIntent.sectionId === section.id) {
                        setDropIntent(null);
                      }
                      if (circuitReorderIntent?.kind === "section-end" && circuitReorderIntent.sectionId === section.id) {
                        setCircuitReorderIntent(null);
                      }
                    }}
                    onDrop={(event) => {
                      if (draggingProjectDeviceId) {
                        void handleDropWithIntent(event, { kind: "new-circuit", sectionId: section.id });
                        return;
                      }
                      if (draggingCircuitId) {
                        void handleCircuitReorderDrop(event, {
                          kind: "section-end",
                          sectionId: section.id,
                          valid: false,
                        });
                      }
                    }}
                  >
                    <td colSpan={columns.length + 1} className="section-drop-cell">
                      <div className="section-content">
                        <strong>{section.displayName}</strong>
                        <div className="section-actions">
                          <button type="button" tabIndex={-1} onClick={() => void handleAddReserveCircuit(section.id)}>
                            Add circuit
                          </button>
                          <button type="button" tabIndex={-1} onClick={() => void handleRenumberSection(section.id)}>
                            Renumber section
                          </button>
                        </div>
                      </div>
                      {dropIntent?.kind === "new-circuit" && dropIntent.sectionId === section.id ? (
                        <span className="drop-hint">drop here to create new circuit</span>
                      ) : null}
                    </td>
                  </tr>
                );
              }

              return (
                <tr
                  key={row.rowKey}
                  className={`${
                    row.rowType === "circuitSummary"
                      ? "summary-row"
                      : row.rowType === "deviceRow"
                        ? "device-row"
                        : row.rowType === "reserveCircuit"
                          ? "empty-circuit-row"
                          : row.rowType === "placeholder"
                            ? "placeholder-row"
                            : ""
                  } ${
                    row.rowType === "placeholder" &&
                    ((dropIntent?.kind === "new-circuit" && dropIntent.sectionId === row.sectionId) ||
                      (deviceMoveIntent?.kind === "move-to-new-circuit" && deviceMoveIntent.sectionId === row.sectionId) ||
                      (circuitReorderIntent?.kind === "section-end" && circuitReorderIntent.sectionId === row.sectionId))
                      ? "drop-target-active"
                      : ""
                  } ${
                    row.rowType === "placeholder" &&
                    circuitReorderIntent?.kind === "section-end" &&
                    circuitReorderIntent.sectionId === row.sectionId &&
                    !circuitReorderIntent.valid
                      ? "drop-target-invalid"
                      : ""
                  } ${
                    row.circuit &&
                    circuitReorderIntent &&
                    (circuitReorderIntent.kind === "before-circuit" || circuitReorderIntent.kind === "after-circuit") &&
                    circuitReorderIntent.targetCircuitId === row.circuit.id &&
                    circuitReorderIntent.valid
                      ? "drop-target-active"
                      : ""
                  } ${
                    row.circuit &&
                    circuitReorderIntent?.kind === "before-circuit" &&
                    circuitReorderIntent.targetCircuitId === row.circuit.id &&
                    circuitReorderIntent.valid
                      ? "circuit-insert-before"
                      : ""
                  } ${
                    row.circuit &&
                    circuitReorderIntent?.kind === "after-circuit" &&
                    circuitReorderIntent.targetCircuitId === row.circuit.id &&
                    circuitReorderIntent.valid
                      ? "circuit-insert-after"
                      : ""
                  } ${
                    row.circuit &&
                    circuitReorderIntent &&
                    (circuitReorderIntent.kind === "before-circuit" || circuitReorderIntent.kind === "after-circuit") &&
                    circuitReorderIntent.targetCircuitId === row.circuit.id &&
                    !circuitReorderIntent.valid
                      ? "drop-target-invalid"
                      : ""
                  } ${
                    row.circuit?.id && draggingCircuitId && row.circuit.id === draggingCircuitId ? "circuit-dragging-block" : ""
                  }`}
                  onClick={() => setActiveSectionId(row.sectionId)}
                  onDragOver={(event) => {
                    if (draggingCircuitId) {
                      if (row.rowType === "placeholder") {
                        const sourceSectionId = findCircuitSectionId(draggingCircuitId);
                        const valid = sourceSectionId === row.sectionId;
                        event.preventDefault();
                        event.dataTransfer.dropEffect = valid ? "move" : "none";
                        setCircuitReorderIntent({ kind: "section-end", sectionId: row.sectionId, valid });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        const sourceSectionId = findCircuitSectionId(draggingCircuitId);
                        if (row.circuit.id === draggingCircuitId) {
                          setCircuitReorderIntent(null);
                          return;
                        }
                        const valid = sourceSectionId === row.sectionId;
                        const rect = (event.currentTarget as HTMLTableRowElement).getBoundingClientRect();
                        const isAfter = event.clientY > rect.top + rect.height / 2;
                        event.preventDefault();
                        event.dataTransfer.dropEffect = valid ? "move" : "none";
                        setCircuitReorderIntent({
                          kind: isAfter ? "after-circuit" : "before-circuit",
                          sectionId: row.sectionId,
                          targetCircuitId: row.circuit.id,
                          valid,
                        });
                      }
                      return;
                    }
                    if (draggingProjectDeviceId) {
                      if (row.rowType === "placeholder") {
                        event.preventDefault();
                        event.dataTransfer.dropEffect = "copy";
                        setDropIntent({ kind: "new-circuit", sectionId: row.sectionId });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        event.preventDefault();
                        event.dataTransfer.dropEffect = "copy";
                        setDropIntent({ kind: "add-to-circuit", circuitId: row.circuit.id, sectionId: row.sectionId });
                      }
                      return;
                    }
                    if (draggingDeviceRowId) {
                      if (row.rowType === "placeholder") {
                        event.preventDefault();
                        event.dataTransfer.dropEffect = "move";
                        setDeviceMoveIntent({ kind: "move-to-new-circuit", sectionId: row.sectionId });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        const sourceCircuitId = findDeviceRowCircuitId(draggingDeviceRowId);
                        if (sourceCircuitId && sourceCircuitId !== row.circuit.id) {
                          event.preventDefault();
                          event.dataTransfer.dropEffect = "move";
                          setDeviceMoveIntent({ kind: "move-to-circuit", circuitId: row.circuit.id, sectionId: row.sectionId });
                        }
                      }
                    }
                  }}
                  onDragLeave={() => {
                    setDropIntent((current) => {
                      if (!current) {
                        return null;
                      }
                      if (current.kind === "new-circuit" && row.rowType === "placeholder" && current.sectionId === row.sectionId) {
                        return null;
                      }
                      if (current.kind === "add-to-circuit" && current.circuitId === row.circuit?.id) {
                        return null;
                      }
                      return current;
                    });
                    setDeviceMoveIntent((current) => {
                      if (!current) {
                        return null;
                      }
                      if (current.kind === "move-to-new-circuit" && row.rowType === "placeholder" && current.sectionId === row.sectionId) {
                        return null;
                      }
                      if (current.kind === "move-to-circuit" && current.circuitId === row.circuit?.id) {
                        return null;
                      }
                      return current;
                    });
                    setCircuitReorderIntent((current) => {
                      if (!current) {
                        return null;
                      }
                      if (current.kind === "section-end" && row.rowType === "placeholder" && current.sectionId === row.sectionId) {
                        return null;
                      }
                      if (
                        (current.kind === "before-circuit" || current.kind === "after-circuit") &&
                        current.targetCircuitId === row.circuit?.id
                      ) {
                        return null;
                      }
                      return current;
                    });
                  }}
                  onDrop={(event) => {
                    if (draggingCircuitId) {
                      if (row.rowType === "placeholder") {
                        const sourceSectionId = findCircuitSectionId(draggingCircuitId);
                        void handleCircuitReorderDrop(event, {
                          kind: "section-end",
                          sectionId: row.sectionId,
                          valid: sourceSectionId === row.sectionId,
                        });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        if (row.circuit.id === draggingCircuitId) {
                          return;
                        }
                        const sourceSectionId = findCircuitSectionId(draggingCircuitId);
                        const rect = (event.currentTarget as HTMLTableRowElement).getBoundingClientRect();
                        const isAfter = event.clientY > rect.top + rect.height / 2;
                        void handleCircuitReorderDrop(event, {
                          kind: isAfter ? "after-circuit" : "before-circuit",
                          sectionId: row.sectionId,
                          targetCircuitId: row.circuit.id,
                          valid: sourceSectionId === row.sectionId,
                        });
                      }
                      return;
                    }
                    if (draggingProjectDeviceId) {
                      if (row.rowType === "placeholder") {
                        void handleDropWithIntent(event, { kind: "new-circuit", sectionId: row.sectionId });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        void handleDropWithIntent(event, {
                          kind: "add-to-circuit",
                          circuitId: row.circuit.id,
                          sectionId: row.sectionId,
                        });
                      }
                      return;
                    }
                    if (draggingDeviceRowId) {
                      if (row.rowType === "placeholder") {
                        void handleDeviceRowDropWithIntent(event, { kind: "move-to-new-circuit", sectionId: row.sectionId });
                        return;
                      }
                      if (row.circuit && row.rowType !== "deviceRow") {
                        void handleDeviceRowDropWithIntent(event, {
                          kind: "move-to-circuit",
                          circuitId: row.circuit.id,
                          sectionId: row.sectionId,
                        });
                      }
                    }
                  }}
                >
                  {columns.map((column) => {
                    const cell = row.cells.find((entry) => entry.cellKey === column.key)!;
                    const isSelected =
                      selectedCell?.rowKey === row.rowKey && selectedCell.cellKey === column.key;
                    const isEditing =
                      editingCell?.rowKey === row.rowKey && editingCell.cellKey === column.key;
                    return (
                      <td
                        key={column.key}
                        className={`${column.numeric ? "num" : ""} ${cell.editable ? "cell-editable" : ""} ${isSelected ? "cell-selected" : ""} ${
                          Boolean(row.device) && column.key === "displayName" && (row.rowType === "deviceRow" || row.rowType === "circuitCompact")
                            ? "device-drag-handle"
                            : ""
                        } ${
                          column.key === "equipmentIdentifier" &&
                          Boolean(row.circuit) &&
                          (row.rowType === "circuitCompact" || row.rowType === "circuitSummary" || row.rowType === "reserveCircuit")
                            ? "circuit-drag-handle"
                            : ""
                        } ${
                          draggingDeviceRowId && row.device?.id === draggingDeviceRowId ? "device-dragging" : ""
                        }`}
                        draggable={
                          !isEditing &&
                          ((Boolean(row.device) &&
                            column.key === "displayName" &&
                            (row.rowType === "deviceRow" || row.rowType === "circuitCompact")) ||
                            (Boolean(row.circuit) &&
                              column.key === "equipmentIdentifier" &&
                              (row.rowType === "circuitCompact" ||
                                row.rowType === "circuitSummary" ||
                                row.rowType === "reserveCircuit")))
                        }
                        onDragStart={(event) => {
                          if (
                            row.circuit &&
                            column.key === "equipmentIdentifier" &&
                            (row.rowType === "circuitCompact" ||
                              row.rowType === "circuitSummary" ||
                              row.rowType === "reserveCircuit")
                          ) {
                            setDraggingProjectDeviceId(null);
                            setDropIntent(null);
                            setDraggingDeviceRowId(null);
                            setDeviceMoveIntent(null);
                            setDraggingCircuitId(row.circuit.id);
                            setCircuitReorderIntent(null);
                            event.dataTransfer.effectAllowed = "move";
                            event.dataTransfer.setData("application/x-circuit-id", row.circuit.id);
                            return;
                          }
                          if (
                            row.device &&
                            column.key === "displayName" &&
                            (row.rowType === "deviceRow" || row.rowType === "circuitCompact")
                          ) {
                            setDraggingProjectDeviceId(null);
                            setDropIntent(null);
                            setDraggingCircuitId(null);
                            setCircuitReorderIntent(null);
                            setDraggingDeviceRowId(row.device.id);
                            setDeviceMoveIntent(null);
                            event.dataTransfer.effectAllowed = "move";
                            event.dataTransfer.setData("application/x-circuit-device-row-id", row.device.id);
                          }
                        }}
                        onDragEnd={() => {
                          setDraggingDeviceRowId(null);
                          setDeviceMoveIntent(null);
                          setDraggingCircuitId(null);
                          setCircuitReorderIntent(null);
                        }}
                        onClick={() => {
                          if (cell.editable) {
                            setSelectedCell({ rowKey: row.rowKey, cellKey: column.key });
                            requestAnimationFrame(() => containerRef.current?.focus());
                          }
                        }}
                        onDoubleClick={() => {
                          if (cell.editable) {
                            startEdit({ rowKey: row.rowKey, cellKey: column.key }, "selectExisting");
                          }
                        }}
                      >
                        {isEditing ? (
                          <input
                            ref={inputRef}
                            value={editingCell.draft}
                            onChange={(event) =>
                              setEditingCell((current) =>
                                current ? { ...current, draft: event.target.value } : current
                              )
                            }
                            onKeyDown={(event) => {
                              if (event.key === "Enter") {
                                event.preventDefault();
                                void commitEdit("stay");
                              } else if (event.key === "Escape") {
                                event.preventDefault();
                                cancelEdit();
                              } else if (event.key === "Tab") {
                                event.preventDefault();
                                void commitEdit(event.shiftKey ? "prev" : "next");
                              }
                            }}
                            onBlur={() => {
                              requestAnimationFrame(() => {
                                const active = document.activeElement as HTMLElement | null;
                                if (!active || !containerRef.current?.contains(active)) {
                                  setEditingCell(null);
                                  requestAnimationFrame(() => containerRef.current?.focus());
                                }
                              });
                            }}
                          />
                        ) : (
                          formatValue(cell.value)
                        )}
                      </td>
                    );
                  })}
                  <td
                    className={`action-cell ${
                      (dropIntent?.kind === "add-to-circuit" && dropIntent.circuitId === row.circuit?.id) ||
                      (deviceMoveIntent?.kind === "move-to-circuit" && deviceMoveIntent.circuitId === row.circuit?.id)
                        ? "drop-target-active"
                        : ""
                    }`}
                  >
                    {row.circuit && row.rowType !== "deviceRow" ? (
                      <>
                        <button
                          type="button"
                          tabIndex={-1}
                          onClick={() => void handleAddManualDevice(row.circuit!, row.sectionId)}
                        >
                          Add manual device
                        </button>
                        <button
                          type="button"
                          tabIndex={-1}
                          onClick={() => void handleDeleteCircuit(row.circuit!.id)}
                        >
                          Delete circuit
                        </button>
                      </>
                    ) : null}
                    {row.device ? (
                      <button type="button" tabIndex={-1} onClick={() => void handleDeleteDevice(row.device!.id)}>
                        Delete device
                      </button>
                    ) : null}
                    {dropIntent?.kind === "new-circuit" && row.rowType === "placeholder" && dropIntent.sectionId === row.sectionId ? (
                      <span className="drop-hint">new circuit in this section</span>
                    ) : null}
                    {dropIntent?.kind === "add-to-circuit" && dropIntent.circuitId === row.circuit?.id ? (
                      <span className="drop-hint">add to this circuit</span>
                    ) : null}
                    {deviceMoveIntent?.kind === "move-to-new-circuit" &&
                    row.rowType === "placeholder" &&
                    deviceMoveIntent.sectionId === row.sectionId ? (
                      <span className="drop-hint">move device to new circuit</span>
                    ) : null}
                    {deviceMoveIntent?.kind === "move-to-circuit" && deviceMoveIntent.circuitId === row.circuit?.id ? (
                      <span className="drop-hint">move device to this circuit</span>
                    ) : null}
                    {circuitReorderIntent?.kind === "section-end" &&
                    row.rowType === "placeholder" &&
                    circuitReorderIntent.sectionId === row.sectionId ? (
                      <span className="drop-hint">
                        {circuitReorderIntent.valid ? "move circuit to section end" : "cross-section move not allowed"}
                      </span>
                    ) : null}
                    {circuitReorderIntent &&
                    (circuitReorderIntent.kind === "before-circuit" || circuitReorderIntent.kind === "after-circuit") &&
                    circuitReorderIntent.targetCircuitId === row.circuit?.id ? (
                      <span className="drop-hint">
                        {circuitReorderIntent.valid
                          ? circuitReorderIntent.kind === "before-circuit"
                            ? "move circuit before this circuit"
                            : "move circuit after this circuit"
                          : "cross-section move not allowed"}
                      </span>
                    ) : null}
                  </td>
                </tr>
              );
            })}
          </tbody>
          </table>
        </div>
      </div>
      <p className="todo-hint">TODO Phase: Ctrl+Plus currently adds circuit at end of active section.</p>
    </div>
  );
}
