<template>
  <g :data-wire-id="props.id">
    <path :d="pathData" fill="none" :stroke="computedStroke" :stroke-width="strokeWidth" stroke-linecap="round"
      stroke-linejoin="round" :class="{ 'wire-active': props.isActive }" @click="handleClick" />
    <!-- 可选：添加连线标签或状态指示器 -->
    <text v-if="showLabel" :x="labelPosition.x" :y="labelPosition.y" class="wire-label">{{ props.constraint || ""
      }}</text>
  </g>
</template>

<script setup lang="ts">
import { useConstraintsStore } from "@/stores/constraints";
import { computed, defineEmits, watch, onMounted, onUnmounted } from "vue";

const { getConstraintColor, onConstraintStateChange } = useConstraintsStore();

interface Props {
  id: string;
  startX: number;
  startY: number;
  endX: number;
  endY: number;
  strokeColor?: string;
  strokeWidth?: number;
  isActive?: boolean;
  routingMode?: "auto" | "orthogonal" | "direct" | "path";
  // 针脚引用属性
  startComponentId?: string;
  startPinId?: string;
  endComponentId?: string;
  endPinId?: string;
  // 添加约束属性
  constraint?: string;
  // 显示标签
  showLabel?: boolean;
  // 路径命令 - 对应diagram.json中的线放置迷你语言
  pathCommands?: string[];
}

const props = withDefaults(defineProps<Props>(), {
  strokeColor: "#4a5568",
  strokeWidth: 2,
  isActive: false,
  routingMode: "orthogonal",
  showLabel: false,
  constraint: "",
});

// 响应约束状态变化的颜色
const constraintColor = computed(() => {
  if (!props.constraint) return props.strokeColor;
  return getConstraintColor(props.constraint);
});

// 计算实际使用的颜色：isActive优先，其次是constraint电平颜色，最后是默认色
const computedStroke = computed(() => {
  if (props.isActive) return "#ff9800";
  return constraintColor.value || props.strokeColor;
});

const emit = defineEmits(["click", "update:active", "update:position"]);

function handleClick(event: MouseEvent) {
  emit("click", { id: props.id, event });
}

// 计算标签位置 - 放在连线中间
const labelPosition = computed(() => {
  return {
    x: (props.startX + props.endX) / 2,
    y: (props.startY + props.endY) / 2 - 5,
  };
});

const pathData = computed(() => {
  // 如果有路径命令，使用路径布线模式
  if (
    props.routingMode === "path" &&
    props.pathCommands &&
    props.pathCommands.length > 0
  ) {
    return calculatePathFromCommands(
      props.startX,
      props.startY,
      props.endX,
      props.endY,
      props.pathCommands,
    );
  }
  // 否则使用正交路径
  return calculateOrthogonalPath(
    props.startX,
    props.startY,
    props.endX,
    props.endY,
  );
});

function calculatePathFromCommands(
  startX: number,
  startY: number,
  endX: number,
  endY: number,
  commands: string[],
) {
  // 找到分隔符索引，通常是 "*"
  const splitterIndex = commands.indexOf("*");
  if (splitterIndex === -1) {
    // 如果没有分隔符，回退到正交路径
    return calculateOrthogonalPath(startX, startY, endX, endY);
  }

  // 分割命令为起点和终点两部分
  const startCommands = commands.slice(0, splitterIndex);
  const endCommands = commands.slice(splitterIndex + 1);

  // 从起点开始生成路径
  let currentX = startX;
  let currentY = startY;

  // 处理起点路径命令
  const pathPoints: [number, number][] = [[currentX, currentY]];

  // 解析并执行起点命令
  for (const cmd of startCommands) {
    const { newX, newY } = executePathCommand(currentX, currentY, cmd);
    currentX = newX;
    currentY = newY;
    pathPoints.push([currentX, currentY]);
  }
  // 从终点开始反向处理
  let endCurrentX = endX;
  let endCurrentY = endY;

  // 保存终点路径点，最后会反转
  const endPathPoints: [number, number][] = [[endCurrentX, endCurrentY]];

  // 解析并执行终点命令（需要从后向前执行反向命令）
  for (let i = endCommands.length - 1; i >= 0; i--) {
    const cmd = reversePathCommand(endCommands[i]);
    const { newX, newY } = executePathCommand(endCurrentX, endCurrentY, cmd);
    endCurrentX = newX;
    endCurrentY = newY;
    endPathPoints.push([endCurrentX, endCurrentY]);
  } // 反转终点路径点，保留所有点
  const reversedEndPoints = [...endPathPoints].reverse();

  // 将两部分路径连接起来
  // 如果终点路径的第一个点与起点路径的最后一个点相同，则去掉重复点
  let combinedPoints;
  if (
    pathPoints.length > 0 &&
    reversedEndPoints.length > 0 &&
    pathPoints[pathPoints.length - 1][0] === reversedEndPoints[0][0] &&
    pathPoints[pathPoints.length - 1][1] === reversedEndPoints[0][1]
  ) {
    combinedPoints = [...pathPoints, ...reversedEndPoints.slice(1)];
  } else {
    combinedPoints = [...pathPoints, ...reversedEndPoints];
  }

  const allPoints = combinedPoints;
  // 检查是否需要添加中间连接点
  if (allPoints.length >= 2) {
    const startPathEndPoint =
      pathPoints.length > 0 ? pathPoints[pathPoints.length - 1] : null;
    const endPathStartPoint =
      reversedEndPoints.length > 0 ? reversedEndPoints[0] : null;

    // 只有当起点路径和终点路径不相连时才添加连接线
    if (
      startPathEndPoint &&
      endPathStartPoint &&
      (startPathEndPoint[0] !== endPathStartPoint[0] ||
        startPathEndPoint[1] !== endPathStartPoint[1])
    ) {
      // 使用正交连接或直接连接
      let middlePoints: [number, number][] = [];

      // 正交连接，添加额外点以确保路径是正交的
      middlePoints = generateOrthogonalConnection(
        startPathEndPoint[0],
        startPathEndPoint[1],
        endPathStartPoint[0],
        endPathStartPoint[1],
      );

      // 在起点路径和终点路径之间插入中间点
      allPoints.splice(pathPoints.length, 0, ...middlePoints);
    }
  } // 生成SVG路径
  if (allPoints.length < 2) {
    // 如果没有足够的点，直接从起点到终点画一条线
    return `M ${startX} ${startY} L ${endX} ${endY}`;
  }

  // 使用所有点生成路径字符串
  let pathStr = `M ${allPoints[0][0]} ${allPoints[0][1]}`;
  for (let i = 1; i < allPoints.length; i++) {
    pathStr += ` L ${allPoints[i][0]} ${allPoints[i][1]}`;
  }

  return pathStr;
}

// 执行单个路径命令
function executePathCommand(
  x: number,
  y: number,
  command: string,
): { newX: number; newY: number } {
  // 解析命令，例如 "down10", "right20", "downright5" 等
  let newX = x;
  let newY = y;

  if (command.startsWith("right")) {
    const distance = parseInt(command.substring(5), 10) || 10;
    newX = x + distance;
    newY = y;
  } else if (command.startsWith("left")) {
    const distance = parseInt(command.substring(4), 10) || 10;
    newX = x - distance;
    newY = y;
  } else if (command.startsWith("down")) {
    if (command.startsWith("downright")) {
      const distance = parseInt(command.substring(9), 10) || 10;
      newX = x + distance;
      newY = y + distance;
    } else if (command.startsWith("downleft")) {
      const distance = parseInt(command.substring(8), 10) || 10;
      newX = x - distance;
      newY = y + distance;
    } else {
      const distance = parseInt(command.substring(4), 10) || 10;
      newX = x;
      newY = y + distance;
    }
  } else if (command.startsWith("up")) {
    if (command.startsWith("upright")) {
      const distance = parseInt(command.substring(7), 10) || 10;
      newX = x + distance;
      newY = y - distance;
    } else if (command.startsWith("upleft")) {
      const distance = parseInt(command.substring(6), 10) || 10;
      newX = x - distance;
      newY = y - distance;
    } else {
      const distance = parseInt(command.substring(2), 10) || 10;
      newX = x;
      newY = y - distance;
    }
  }

  return { newX, newY };
}

// 生成两点之间的正交连接点
function generateOrthogonalConnection(
  x1: number,
  y1: number,
  x2: number,
  y2: number,
): [number, number][] {
  const dx = x2 - x1;
  const dy = y2 - y1;

  if (dx === 0 || dy === 0) {
    // 如果在同一水平或垂直线上，不需要额外点
    return [];
  }

  // 选择先水平移动还是先垂直移动
  const middlePoints: [number, number][] = [];

  if (Math.abs(dx) > Math.abs(dy)) {
    // 先水平后垂直
    middlePoints.push([x1 + dx / 2, y1]);
    middlePoints.push([x1 + dx / 2, y2]);
  } else {
    // 先垂直后水平
    middlePoints.push([x1, y1 + dy / 2]);
    middlePoints.push([x2, y1 + dy / 2]);
  }

  return middlePoints;
}

// 计算正交路径
function calculateOrthogonalPath(
  startX: number,
  startY: number,
  endX: number,
  endY: number,
) {
  // 计算两点之间的水平和垂直距离
  const dx = endX - startX;
  const dy = endY - startY;

  // 如果在同一水平或垂直线上，直接连线
  if (dx === 0 || dy === 0) {
    return `M ${startX} ${startY} L ${endX} ${endY}`;
  }

  const absDx = Math.abs(dx);
  const absDy = Math.abs(dy);
  if (absDx > absDy) {
    // 先水平移动，然后垂直移动
    const middleX = startX + dx * 0.5;
    return `M ${startX} ${startY} L ${middleX} ${startY} L ${middleX} ${endY} L ${endX} ${endY}`;
  } else {
    // 先垂直移动，然后水平移动
    const middleY = startY + dy * 0.5;
    return `M ${startX} ${startY} L ${startX} ${middleY} L ${endX} ${middleY} L ${endX} ${endY}`;
  }
}

// 添加反转命令函数 - 将方向命令反转
function reversePathCommand(command: string): string {
  // 提取距离部分
  const distanceMatch = command.match(/\d+$/);
  const distance = distanceMatch ? distanceMatch[0] : "10"; // 默认距离是10

  // 根据命令类型返回反向命令
  // 水平方向反转
  if (command.startsWith("right")) {
    return `left${distance}`;
  } else if (command.startsWith("left")) {
    return `right${distance}`;
  }
  // 垂直和斜向反转
  else if (command.startsWith("down")) {
    if (command.startsWith("downright")) {
      return `upleft${distance}`;
    } else if (command.startsWith("downleft")) {
      return `upright${distance}`;
    } else {
      return `up${distance}`;
    }
  } else if (command.startsWith("up")) {
    if (command.startsWith("upright")) {
      return `downleft${distance}`;
    } else if (command.startsWith("upleft")) {
      return `downright${distance}`;
    } else {
      return `down${distance}`;
    }
  }

  // 默认情况下，无法反转就返回原命令
  return command;
}

// 监听约束状态变化
let unsubscribe: (() => void) | null = null;

onMounted(() => {
  // 监听约束状态变化
  if (props.constraint) {
    unsubscribe = onConstraintStateChange((constraint, level) => {
      if (constraint === props.constraint) {
        // 约束状态变化，触发重新渲染
      }
    });
  }
});

onUnmounted(() => {
  // 清理监听
  if (unsubscribe) {
    unsubscribe();
  }
});

// 监听约束属性变化
watch(
  () => props.constraint,
  (newConstraint, oldConstraint) => {
    if (unsubscribe) {
      unsubscribe();
      unsubscribe = null;
    }

    if (newConstraint) {
      unsubscribe = onConstraintStateChange((constraint, level) => {
        if (constraint === newConstraint) {
          // 约束状态变化，触发重新渲染
        }
      });
    }
  },
);

// 暴露方法，用于获取这条连线的信息
defineExpose({
  id: props.id,
  getInfo: () => ({
    id: props.id,
    startComponentId: props.startComponentId,
    startPinId: props.startPinId,
    endComponentId: props.endComponentId,
    endPinId: props.endPinId,
    constraint: props.constraint,
  }),
  // 更新连线位置
  updatePosition: (
    newStartX: number,
    newStartY: number,
    newEndX: number,
    newEndY: number,
  ) => {
    // 由于 props 是只读的，我们只能通过事件通知父组件更新
    emit("update:position", {
      id: props.id,
      startX: newStartX,
      startY: newStartY,
      endX: newEndX,
      endY: newEndY,
    });
  },
  // 获取连线的针脚情况
  getPinPosition: () => null, // 为了与其他组件接口一致，但Wire不是针脚组件
  // 获取连线的路由模式
  getRoutingMode: () => props.routingMode,
  // 设置连线状态（如高亮等）
  setActive: (active: boolean) => {
    emit("update:active", active);
  },
});
</script>

<style scoped>
.wire-active {
  stroke-dasharray: 5;
  animation: dash 0.5s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: 10;
  }
}

.wire-label {
  font-size: 10px;
  fill: #666;
  text-anchor: middle;
  pointer-events: none;
  user-select: none;
}
</style>
