"use client";

import { memo } from "react";
import { Handle, Position, useConnection, type NodeProps } from "@xyflow/react";
import { layerFromNeoLabel, LAYER_COLOURS, type SerializedViewElement } from "@/lib/ea-types";
import { StructuredValueStreamNode } from "./StructuredValueStreamNode";
import { ValueStreamStageNode } from "./ValueStreamStageNode";
import { BpmnTaskNode } from "./BpmnTaskNode";
import { BpmnGatewayNode } from "./BpmnGatewayNode";
import { BpmnEventNode } from "./BpmnEventNode";
import { BpmnLaneNode } from "./BpmnLaneNode";

// One source handle per side. ConnectionMode.Loose allows source→source connections,
// so target handles are unnecessary. Floating edge routing uses node intersection, not handle IDs.
const SIDES = [
  { position: Position.Top,    id: "t" },
  { position: Position.Right,  id: "r" },
  { position: Position.Bottom, id: "b" },
  { position: Position.Left,   id: "l" },
];

export const EaElementNode = memo(function EaElementNode({ id, data, selected }: NodeProps) {
  const nodeData = data as SerializedViewElement;
  const layer = layerFromNeoLabel(nodeData.elementType.neoLabel);
  const colours = LAYER_COLOURS[layer] ?? { bg: "#CCE5FF", border: "#4a90d9" };

  const connection = useConnection();
  const isConnecting = connection.inProgress;
  const isThisSource = isConnecting && connection.fromNode?.id === id;

  const isReference = nodeData.mode === "reference";
  const isPropose = nodeData.mode === "propose";

  const baseBorder = isReference
    ? `2px dashed ${colours.border}`
    : isPropose
    ? `2px solid #7c8cf8`
    : `2px solid ${colours.border}`;

  const targetGlow = isConnecting && !isThisSource
    ? `0 0 0 2px ${colours.border}, 0 0 10px 3px ${colours.border}55`
    : undefined;
  const selectionGlow = isPropose && selected ? "0 0 0 2px #7c8cf833" : undefined;

  const displayName = isPropose && nodeData.proposedProperties?.["name"]
    ? String(nodeData.proposedProperties["name"])
    : nodeData.element.name;

  // Handles visible on hover or while connecting
  const handleVisible = isConnecting && !isThisSource;
  const handleStyle = {
    width: 10,
    height: 10,
    borderRadius: "50%",
    background: colours.border,
    border: `1px solid ${colours.bg}`,
    opacity: handleVisible ? 1 : 0,
    transition: "opacity 0.12s ease",
    zIndex: 10,
  };

  if (nodeData.rendererHint === "nested_chevron_sequence") {
    return (
      <div style={{ position: "relative" }}>
        {SIDES.map(({ position, id: handleId }) => (
          <Handle
            key={handleId}
            type="source"
            id={handleId}
            position={position}
            style={handleStyle}
          />
        ))}
        <StructuredValueStreamNode data={nodeData} selected={selected} />
      </div>
    );
  }

  if (nodeData.elementType.slug === "value_stream_stage") {
    return <ValueStreamStageNode data={nodeData} selected={selected} />;
  }

  // ── BPMN 2.0 dispatch ─────────────────────────────────────────────────
  if (nodeData.elementType.neoLabel.startsWith("BPMN__")) {
    const slug = nodeData.elementType.slug;
    const bpmnHandles = (
      <>
        {SIDES.map(({ position, id: handleId }) => (
          <Handle key={handleId} type="source" id={handleId} position={position} style={handleStyle} />
        ))}
      </>
    );

    // Gateways (diamond)
    if (slug.includes("gateway")) {
      return (
        <div style={{ position: "relative" }}>
          {bpmnHandles}
          <BpmnGatewayNode data={nodeData} selected={selected} />
        </div>
      );
    }
    // Events (circles)
    if (slug.includes("event")) {
      return (
        <div style={{ position: "relative" }}>
          {bpmnHandles}
          <BpmnEventNode data={nodeData} selected={selected} />
        </div>
      );
    }
    // Pools and lanes (swimlane containers)
    if (slug === "bpmn_pool" || slug === "bpmn_lane") {
      return (
        <div style={{ position: "relative" }}>
          {bpmnHandles}
          <BpmnLaneNode data={nodeData} selected={selected} />
        </div>
      );
    }
    // All task types and activities (rounded rectangle)
    return (
      <div style={{ position: "relative" }}>
        {bpmnHandles}
        <BpmnTaskNode data={nodeData} selected={selected} />
      </div>
    );
  }

  return (
    <div
      style={{
        padding: "8px 10px",
        background: colours.bg,
        border: baseBorder,
        borderRadius: 5,
        boxShadow: targetGlow ?? selectionGlow,
        opacity: isReference ? 0.85 : 1,
        minWidth: 120,
        maxWidth: 160,
        position: "relative",
        userSelect: "none",
        transition: "box-shadow 0.15s ease",
      }}
      onMouseEnter={(e) => {
        e.currentTarget.querySelectorAll<HTMLElement>(".react-flow__handle").forEach((h) => {
          h.style.opacity = "1";
        });
      }}
      onMouseLeave={(e) => {
        if (!connection.inProgress) {
          e.currentTarget.querySelectorAll<HTMLElement>(".react-flow__handle").forEach((h) => {
            h.style.opacity = "0";
          });
        }
      }}
    >
      {SIDES.map(({ position, id }) => (
        <Handle
          key={id}
          type="source"
          id={id}
          position={position}
          style={handleStyle}
        />
      ))}

      <div style={{ fontSize: 7, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.04em", color: "#336", marginBottom: 2 }}>
        {nodeData.elementType.name} · {nodeData.mode}
      </div>
      <div style={{ fontSize: 11, fontWeight: 600, color: "#112" }}>{displayName}</div>
      <div style={{ fontSize: 10, color: "#446", marginTop: 2 }}>
        {nodeData.element.lifecycleStage} · {nodeData.element.lifecycleStatus}
      </div>
      {isReference && (
        <div style={{ position: "absolute", top: 4, right: 6, fontSize: 10, color: "#336", opacity: 0.7 }}>🔒</div>
      )}
      {isPropose && (
        <div style={{ position: "absolute", top: 4, right: 6, fontSize: 10, color: "var(--dpf-accent)" }}>✏️</div>
      )}
    </div>
  );
});
