import type { FC } from "react";
import * as d3 from "d3";
import type { Goal } from "../../../types/goal";
import styles from "../styles/Edge.module.css";
import { Tooltip } from "@douyinfe/semi-ui";

// 主链连接线：根据目标状态决定颜色与箭头，支持选中高亮
interface EdgeProps {
  link: d3.HierarchyPointLink<Goal>;
  label?: string;
  highlighted: boolean;
  dimmed: boolean;
  onClick: () => void;
  mode?: "line" | "label";
  curveOffset?: number;
}

export const Edge: FC<EdgeProps> = ({ link, label, highlighted, dimmed, onClick, mode = "line", curveOffset = 0 }) => {
  const { source, target } = link;
  const truncateMiddle = (text: string, limit: number) => {
    if (text.length <= limit) return text;
    return `${text.slice(0, 2)}...${text.slice(-2)}`;
  };

  const createPath = () => {
    const sourceX = source.x;
    const sourceY = source.y;
    const targetX = target.x;
    const targetY = target.y;
    const nodeHalfW = 80;
    const direction = targetX >= sourceX ? 1 : -1;
    const startX = sourceX + direction * nodeHalfW;
    const endX = targetX - direction * nodeHalfW;
    const midX = (startX + endX) / 2;

    if (curveOffset !== 0) {
      return `M${startX},${sourceY} C${midX},${sourceY + curveOffset} ${midX},${targetY + curveOffset} ${endX},${targetY}`;
    }

    return `M${startX},${sourceY} C${midX},${sourceY} ${midX},${targetY} ${endX},${targetY}`;
  };

  const getMarkerUrl = () => {
    if (highlighted) return "url(#arrow-selected)";
    const status = target.data.status;
    switch (status) {
      case "completed":
        return "url(#arrow-success)";
      case "failed":
        return "url(#arrow-error)";
      case "running":
        return "url(#arrow-running)";
      default:
        return "url(#arrow-default)";
    }
  };

  const getStrokeColor = () => {
    if (highlighted) return "#ff6b6b";
    const status = target.data.status;
    switch (status) {
      case "completed":
        return "#00c853";
      case "failed":
        return "#f44336";
      case "running":
        return "#ff9800";
      default:
        return "#4e79a7";
    }
  };

  const renderLabel = () => {
    if (!label) return null;
    const sourceX = source.x;
    const sourceY = source.y;
    const targetX = target.x;
    const targetY = target.y;
    const nodeHalfW = 80;
    const direction = targetX >= sourceX ? 1 : -1;
    const startX = sourceX + direction * nodeHalfW;
    const endX = targetX - direction * nodeHalfW;
    const midX = (startX + endX) / 2;
    const midY = (sourceY + targetY) / 2 + curveOffset * 0.75;

    const truncated = truncateMiddle(label, 6);

    return (
      <g
        transform={`translate(${midX},${midY})`}
        style={{ cursor: "pointer" }}
        onClick={(e) => {
          e.stopPropagation();
          onClick();
        }}
      >
        <rect
          x={-30}
          y={-10}
          width={60}
          height={20}
          rx={4}
          fill="#fff"
          fillOpacity={1}
          stroke="#fff"
          strokeWidth={1}
        />
        <Tooltip
          content={label}
          position="top"
        >
          <text
            textAnchor="middle"
            dy="0.35em"
            fontSize={11}
            fill="#1f2937"
            style={{ userSelect: "none" }}
          >
            {truncated}
          </text>
        </Tooltip>
      </g>
    );
  };

  return (
    <g className={styles.edge}>
      {mode === "line" && (
        <>
          <path
            d={createPath()}
            fill="none"
            stroke="transparent"
            strokeWidth={15}
            style={{ cursor: "pointer" }}
            onClick={(e) => {
              e.stopPropagation();
              onClick();
            }}
          />
          <path
            d={createPath()}
            fill="none"
            stroke={getStrokeColor()}
            strokeWidth={highlighted ? 3 : 2}
            markerEnd={getMarkerUrl()}
            opacity={dimmed ? 0.2 : 1}
            style={{ pointerEvents: "none" }}
          />
        </>
      )}
      {mode === "label" && renderLabel()}
    </g>
  );
};
