import React, { useEffect, useRef } from 'react';
import * as cornerstone from '@cornerstonejs/core';
import type { Types } from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
import { annotation, SplineROITool } from '@cornerstonejs/tools';
import { eventTarget } from '@cornerstonejs/core';
import { registerGlobalTools } from '@/utils/cornerstoneToolsSetup';
import { MeasurementToolManager } from '@/utils/measurementToolManager';
import TibialPlateauAngleTool from '@/components/measures/TibialPlateauAngleTool';
import DARAMeasurementTool from '@/components/measures/DARAMeasurementTool';
import HipDIMeasurementTool from '@/components/measures/HipDIMeasurementTool';
import HipNHAAngleMeasurementTool from '@/components/measures/HipNHAAngleMeasurementTool';
import VHSMeasurementTool from '@/components/measures/VHSMeasurementTool';
import TPLOMeasurementTool from '@/components/measures/TPLOMeasurementTool';
import TTAMeasurementTool from '@/components/measures/TTAMeasurementTool';
import CBLOMeasurementTool from '@/components/measures/CBLOMeasurementTool';
import HipCoverageMeasurementTool from '@/components/measures/HipCoverageMeasurementTool';
import HipDorsalCoverageTool from '@/components/measures/HipDorsalCoverageTool';
import CircleCenterMeasurementTool from '@/components/measures/CircleCenterMeasurementTool';
import MidlineMeasurementTool from '@/components/measures/MidlineMeasurementTool';
import FindMidpointMeasurementTool from '@/components/measures/FindMidpointMeasurementTool';
import VerticalTiltMeasurementTool from '@/components/measures/VerticalTiltMeasurementTool';
import HorizontalTiltMeasurementTool from '@/components/measures/HorizontalTiltMeasurementTool';
import DicomOverlayTool from '@/components/overlay/DicomOverlayTool';
import ImageViewerErrorBoundary from './ImageViewerErrorBoundary';
import { boolean } from 'zod';
import { EVENTS } from '@cornerstonejs/core';
import { useSelector } from 'react-redux';
import { selectOverlayEnabled } from '@/states/view/dicomOverlaySlice';
import PolygonLengthMeasurementTool from '@/components/measures/PolygonLengthMeasurementTool';
import PolylineLengthMeasurementTool from '@/components/measures/PolylineLengthMeasurementTool';

const {
  MagnifyTool,
  PanTool,
  WindowLevelTool,
  StackScrollTool,
  ZoomTool,
  LabelTool,
  LengthTool,
  AngleTool,//角度测量工具
  ToolGroupManager,
  Enums: csToolsEnums,
  PlanarRotateTool,
} = cornerstoneTools;
const { MouseBindings } = csToolsEnums;
// let toolGroup: cornerstoneTools.Types.IToolGroup;
// let currentViewportId: string;

/**
 * 增强错误信息，添加更多上下文
 */
function enhanceError(
  error: unknown,
  context: {
    imageUrls: string[];
    imageIndex: number;
    viewportId: string;
  }
): Error {
  const baseError = error instanceof Error ? error : new Error(String(error));
  const { imageUrls, imageIndex, viewportId } = context;
  const contextInfo = {
    imageUrls,
    imageIndex,
    viewportId,
    timestamp: new Date().toISOString(),
    userAgent: navigator.userAgent
  };

  // 创建增强的错误消息
  const enhancedMessage = `[${context.viewportId}] 图像加载失败: ${baseError.message}
    上下文信息: ${JSON.stringify(contextInfo, null, 2)}`;

  const enhancedError = new Error(enhancedMessage);
  enhancedError.name = `ImageLoadError`;
  enhancedError.stack = `${enhancedError.name}: ${enhancedMessage}\n原错误堆栈: ${baseError.stack}`;

  return enhancedError;
}

/**
 * 判断是否为严重错误，需要抛出给 Error Boundary
 */
function isCriticalError(error: Error): boolean {
  const message = error.message.toLowerCase();

  // 以下类型的错误被认为是严重的，需要用户干预
  const criticalErrors = [
    '图像url列表为空',
    '图像索引无效',
    '401', // 认证失败
    '403', // 权限不足
    '404', // 文件不存在
    '500', // 服务器错误
    '认证失败',
    '权限不足',
    'unauthorized',
    'forbidden',
    'not found',
    'internal server error'
  ];

  return criticalErrors.some(keyword => message.includes(keyword));
}

function getToolgroupByViewportId(currentViewportId: string) {
  const toolGroup = ToolGroupManager.getToolGroup(
    `STACK_TOOL_GROUP_ID_${currentViewportId}`
  );
  if (!toolGroup) {
    console.log('toolGroup not found');
    throw new Error('Tool group not found');
  }
  return toolGroup;
}
function overlayRedRectangle(currentViewportId: string) {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  const viewportElement = viewport.element;
  const annotations = cornerstoneTools.annotation.state.getAnnotations(
    'LinearSplineROI',
    viewportElement
  );

  if (!annotations || annotations.length === 0) {
    console.log('No ROI annotations found');
    return;
  }

  const annotation = annotations[annotations.length - 1];
  const points = annotation?.data?.handles?.points;

  // 创建一个覆盖 Canvas
  const canvas = document.createElement('canvas');
  canvas.style.position = 'absolute';
  canvas.width = viewportElement.clientWidth;
  canvas.height = viewportElement.clientHeight;
  viewportElement.firstChild?.appendChild(canvas);

  const ctx = canvas.getContext('2d');
  if (!ctx) {
    throw new Error('Failed to get 2D context from canvas');
  }
  ctx.fillStyle = 'rgba(0, 0, 0, 1)';

  // 将 ROI 坐标转换为 Canvas 坐标
  if (!points) {
    console.log('No points found in handles');
    return;
  }

  // Convert all points to canvas coordinates
  const z = viewport.getCurrentImageIdIndex() || 0;
  const canvasPoints = points.map((point: Types.Point2 | Types.Point3) => {
    const point3D: Types.Point3 =
      point.length === 2 ? [point[0], point[1], z] : point;
    return viewport.worldToCanvas(point3D);
  });

  // Log for debugging
  console.log('Canvas Points:', canvasPoints);

  // Draw the polygon
  ctx.beginPath();
  ctx.rect(0, 0, canvas.width, canvas.height); // Full canvas for evenodd rule
  ctx.moveTo(canvasPoints[0][0], canvasPoints[0][1]); // Start at the first point
  for (let i = 1; i < canvasPoints.length; i++) {
    ctx.lineTo(canvasPoints[i][0], canvasPoints[i][1]); // Connect to subsequent points
  }
  ctx.closePath(); // Close the polygon
  ctx.fill('evenodd'); // Fill with red
}

function registerTools(viewportId, renderingEngineId) {
  // 确保全局工具已注册（只会执行一次）
  registerGlobalTools();

  // 创建该 viewport 的工具组
  const toolGroupId = `STACK_TOOL_GROUP_ID_${viewportId}`;
  const toolGroupTmp = ToolGroupManager.createToolGroup(toolGroupId);
  if (!toolGroupTmp) {
    console.error(
      `[registerTools] Failed to create tool group for viewport: ${viewportId}`
    );
    return;
  }
  const toolGroup = toolGroupTmp;

  // 添加工具到工具组
  toolGroup.addTool(MagnifyTool.toolName);
  toolGroup.addTool(PanTool.toolName);
  toolGroup.addTool(WindowLevelTool.toolName);
  toolGroup.addTool(StackScrollTool.toolName);
  toolGroup.addTool(ZoomTool.toolName);
  toolGroup.addTool(LabelTool.toolName);
  toolGroup.addTool(PlanarRotateTool.toolName);
  toolGroup.addTool(LengthTool.toolName); // 添加线段测量工具
  toolGroup.addTool(AngleTool.toolName); // 添加角度测量工具
  toolGroup.addTool(TibialPlateauAngleTool.toolName); // 添加胫骨平台夹角测量工具
  toolGroup.addTool(DARAMeasurementTool.toolName); // 添加髋臼水平角测量工具
  toolGroup.addTool(HipDIMeasurementTool.toolName); // 添加髋关节牵引指数测量工具
  toolGroup.addTool(HipNHAAngleMeasurementTool.toolName); // 添加髋关节水平角测量工具
  toolGroup.addTool(VHSMeasurementTool.toolName); // 添加心锥比测量工具
  toolGroup.addTool(TPLOMeasurementTool.toolName); // 添加TPLO测量工具
  toolGroup.addTool(TTAMeasurementTool.toolName); // 添加TTA测量工具
  toolGroup.addTool(CBLOMeasurementTool.toolName); // 添加CBLO测量工具
  toolGroup.addTool(HipCoverageMeasurementTool.toolName); // 添加股骨头覆盖率测量工具
  toolGroup.addTool(HipDorsalCoverageTool.toolName); // 添加髋臼背覆盖测量工具
  toolGroup.addTool(CircleCenterMeasurementTool.toolName); // 添加找圆心测量工具
  toolGroup.addTool(MidlineMeasurementTool.toolName); // 添加找中线测量工具
  toolGroup.addTool(FindMidpointMeasurementTool.toolName); // 添加找中点测量工具
  toolGroup.addTool(VerticalTiltMeasurementTool.toolName); // 添加直线垂直倾斜度测量工具
  toolGroup.addTool(HorizontalTiltMeasurementTool.toolName); // 添加直线水平倾斜度测量工具
  toolGroup.addTool(DicomOverlayTool.toolName); // 添加DICOM四角信息显示工具
  toolGroup.addTool(PolygonLengthMeasurementTool.toolName); // 添加多边形长度测量工具
  toolGroup.addTool(PolylineLengthMeasurementTool.toolName); // 添加拆线长度测量工具

  // 设置默认工具状态
  setupDefaultToolStates(toolGroup);

  // 添加 viewport 到工具组
  toolGroup.addViewport(viewportId, renderingEngineId);

  console.log(`[registerTools] Tools registered for viewport: ${viewportId}`);
}

/**
 * 设置默认工具状态
 */
function setupDefaultToolStates(toolGroup: cornerstoneTools.Types.IToolGroup) {
  // 设置平移工具（中键）
  toolGroup.setToolActive(PanTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Auxiliary, // Middle Click
      },
    ],
  });

  // 设置缩放工具（右键）
  toolGroup.setToolActive(ZoomTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Secondary, // Right Click
      },
    ],
  });

  // 设置滚轮滚动工具
  toolGroup.setToolActive(StackScrollTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Wheel, // Mouse Wheel
      },
    ],
  });

  // 其他工具默认为被动状态
  toolGroup.setToolPassive(MagnifyTool.toolName);
  toolGroup.setToolPassive(WindowLevelTool.toolName);
  toolGroup.setToolPassive(LabelTool.toolName);
  toolGroup.setToolPassive(PlanarRotateTool.toolName);
  toolGroup.setToolPassive(LengthTool.toolName);
  toolGroup.setToolPassive(AngleTool.toolName);
  toolGroup.setToolPassive(TibialPlateauAngleTool.toolName);
  toolGroup.setToolPassive(DARAMeasurementTool.toolName);
  toolGroup.setToolPassive(HipDIMeasurementTool.toolName);
  toolGroup.setToolPassive(HipNHAAngleMeasurementTool.toolName);
  toolGroup.setToolPassive(VHSMeasurementTool.toolName);
  toolGroup.setToolPassive(TPLOMeasurementTool.toolName);
  toolGroup.setToolPassive(TTAMeasurementTool.toolName);
  toolGroup.setToolPassive(CBLOMeasurementTool.toolName);
  toolGroup.setToolPassive(HipCoverageMeasurementTool.toolName);
  toolGroup.setToolPassive(HipDorsalCoverageTool.toolName);
  toolGroup.setToolPassive(CircleCenterMeasurementTool.toolName);
  toolGroup.setToolPassive(MidlineMeasurementTool.toolName);
  toolGroup.setToolPassive(FindMidpointMeasurementTool.toolName);
  toolGroup.setToolPassive(VerticalTiltMeasurementTool.toolName);
  toolGroup.setToolPassive(HorizontalTiltMeasurementTool.toolName);
  toolGroup.setToolPassive(PolygonLengthMeasurementTool.toolName);
  toolGroup.setToolPassive(PolylineLengthMeasurementTool.toolName);
}
export function addLMark(currentViewportId: string): void {
  // Implement the logic to add an L mark
  console.log('Adding L Mark viewport id : ', currentViewportId);
  const toolGroup = getToolgroupByViewportId(currentViewportId);
  // currentViewportId = viewportId;
  toolGroup.setToolActive(LabelTool.toolName, {
    bindings: [
      // {
      //   mouseButton: MouseBindings.Primary, // Left Click
      // },
    ],
  });
  const position: Types.Point3 = [100, 100, 0]; // Example position
  const text = 'L'; // Predefined text
  LabelTool.hydrate(currentViewportId, position, text);
  toolGroup.setToolPassive(LabelTool.toolName, {
    removeAllBindings: true,
  });
  // const enabledElement = cornerstone.getEnabledElementByViewportId(currentViewportId);
  // cursors.elementCursor.resetElementCursor(elementRef.current as HTMLDivElement);
}
export function addRLabel(viewportId) {
  const toolGroup = getToolgroupByViewportId(viewportId);
  toolGroup.setToolActive(LabelTool.toolName, {
    bindings: [],
  });
  const element = document.getElementById(viewportId);
  const elementHeight = element ? element.getBoundingClientRect().height : 0;
  const position: Types.Point3 = [100, elementHeight / 2, 0]; // Example position
  const text = 'R'; // Predefined text
  LabelTool.hydrate(viewportId, position, text);
  toolGroup.setToolPassive(LabelTool.toolName, { removeAllBindings: true });
}

export function adjustBrightnessAndContrast(currentViewportId: string) {
  const toolGroup = getToolgroupByViewportId(currentViewportId);
  const planar = toolGroup.getToolInstance(WindowLevelTool.toolName); // Reset rotation angle
  const isActive = planar.mode === csToolsEnums.ToolModes.Active;
  if (isActive) {
    toolGroup.setToolPassive(WindowLevelTool.toolName, {
      removeAllBindings: true,
    });
  } else {
    toolGroup.setToolActive(WindowLevelTool.toolName, {
      bindings: [
        {
          mouseButton: MouseBindings.Primary, // Left Click
        },
      ],
    });
  }
}

/**
 * 防抖工具函数
 * @param func 要防抖的函数
 * @param wait 等待时间（毫秒）
 * @returns 防抖后的函数
 */
function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
  let timeout: NodeJS.Timeout | null = null;
  return (...args: Parameters<T>) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

function containImage(viewport:cornerstone.StackViewport) {
    viewport.getRenderingEngine().resize(/* immediate */ true);
    console.log(`使用 resetCamera方式`)
    viewport.resetCamera({ resetPan: true, resetZoom: true }); // 重置 pan/zoom 到 contain
    viewport.render();
}

/**
 * 保持宽高比的图像适应函数
 * 确保图像完全显示在容器内，同时保持原始宽高比（可能会有黑边）
 * @param currentViewportId 当前视口ID
 */
export function fitImageWithAspectRatio(currentViewportId: string): void {
  try {
    console.log(`[fitImageWithAspectRatio] 重新适配大小`)
    const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
      .viewport as cornerstone.StackViewport;

    if (!viewport) {
      console.warn(`[fitImageWithAspectRatio] Viewport not found: ${currentViewportId}`);
      return;
    }
    containImage(viewport)

  } catch (error) {
    console.error(`[fitImageWithAspectRatio] Error fitting image with aspect ratio:`, error);
  }
}

export function fitImageSize(currentViewportId: string) {
  // 使用新的保持宽高比的适应函数
  fitImageWithAspectRatio(currentViewportId);
}

export function deleteSelectedMark(currentViewportId: string): void {
  const viewport =
    cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
  const allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();

  // 删除所有 LabelTool 创建的标记（包括 L/R 标记、预定义标记、自定义标记、时间戳标记）
  for (const annotation of allAnnotations) {
    if (annotation.metadata?.toolName === LabelTool.toolName) {
      cornerstoneTools.annotation.state.removeAnnotation(
        annotation.annotationUID!
      );
    }
  }

  viewport.render();
}

export function addMark(currentViewportId: string): void {
  // Implement the logic to add a mask
  console.log('Adding Mask');
  // Add the specific logic to add a mask here
  cornerstoneTools.addTool(SplineROITool);
  const toolGroup = getToolgroupByViewportId(currentViewportId);
  toolGroup.addTool(SplineROITool.toolName);
  toolGroup.addToolInstance('LinearSplineROI', SplineROITool.toolName, {
    spline: {
      type: SplineROITool.SplineTypes.Linear,
    },
  });
  toolGroup.setToolActive('LinearSplineROI', {
    bindings: [{ mouseButton: MouseBindings.Primary }],
  });
}

/**
 * 添加自定义文本标记到图像
 */
export function addCustomMark(currentViewportId: string, text: string): void {
  console.log(`Adding custom mark: ${text} to viewport: ${currentViewportId}`);

  const toolGroup = getToolgroupByViewportId(currentViewportId);

  // 激活标签工具
  toolGroup.setToolActive(LabelTool.toolName, {
    bindings: [],
  });

  // 获取视口元素和位置
  const element = document.getElementById(currentViewportId);
  if (!element) {
    console.error(`Element not found for viewport: ${currentViewportId}`);
    return;
  }

  // 计算标记位置（图像中心位置）
  const elementHeight = element.getBoundingClientRect().height;
  const elementWidth = element.getBoundingClientRect().width;
  const position: Types.Point3 = [elementWidth / 2, elementHeight / 2, 0];

  // 添加标签
  LabelTool.hydrate(currentViewportId, position, text);

  // 恢复工具状态
  toolGroup.setToolPassive(LabelTool.toolName, {
    removeAllBindings: true,
  });

  console.log(`Custom mark "${text}" added successfully`);
}

export function remoteMask(currentViewportId: string): void {
  // 1. 获取所有 annotation
  const all = annotation.state.getAllAnnotations();

  // 2. 过滤出 LinearSplineROI 产生的
  const toRemove = all.filter(
    (a) => a.metadata?.toolName === 'LinearSplineROI'
  );

  // 3. 逐条删掉
  toRemove.forEach((a) => {
    if (a.annotationUID) {
      annotation.state.removeAnnotation(a.annotationUID);
    }
  });
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  viewport.render();

  console.log('Deleting Digital Mask');

  const viewportElement = viewport.element;
  const firstChild = viewportElement.firstChild;
  if (firstChild) {
    const canvasElements = Array.from(firstChild.childNodes).filter(
      (child): child is Element =>
        child instanceof Element && child.tagName === 'CANVAS'
    );
    canvasElements.slice(1).forEach((canvas) => {
      firstChild.removeChild(canvas);
    });
  }
}
export function HorizontalFlip(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // 切换水平翻转状态
  const { flipHorizontal } = viewport.getCamera();
  viewport.setCamera({ flipHorizontal: !flipHorizontal });
  console.log('Flipping Image Horizontally');
}

export function VerticalFlip(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // 切换竖直翻转状态
  const { flipVertical } = viewport.getCamera();
  viewport.setCamera({ flipVertical: !flipVertical });
}


export function RotateCounterclockwise90(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // 获取当前相机
  const camera = viewport.getCamera();

  // 计算新的旋转角度（当前角度 + 90度）
  const newRotation = (camera.rotation ?? 0) + 90;

  // 但计算viewUp向量时，我们应该使用90度的弧度，而不是新角度的弧度！
  const ninetyDegreesRadians = (90 * Math.PI) / 180;

  // 获取当前的viewUp向量
  const currentViewUp = camera.viewUp || [0, 1, 0];

  // 计算旋转后的viewUp向量（这才是正确的相对旋转）
  const newViewUp: [number, number, number] = [
    currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
    currentViewUp[1] * Math.sin(ninetyDegreesRadians),
    currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
    currentViewUp[1] * Math.cos(ninetyDegreesRadians),
    0,
  ];

  // 设置新的相机参数
  viewport.setCamera({
    ...camera,
    viewUp: newViewUp,
    rotation: newRotation % 360, // 确保角度在0-359范围内
  });

  viewport.render();

  console.log('Rotating Image Counterclockwise 90°');
}

export function RotateClockwise90(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  const camera = viewport.getCamera();
  // 计算新的旋转角度（当前角度 + 90度）
  const newRotation = (camera.rotation ?? 0) - 90;

  // 但计算viewUp向量时，我们应该使用90度的弧度，而不是新角度的弧度！
  const ninetyDegreesRadians = (90 * Math.PI) / 180;

  // 获取当前的viewUp向量
  const currentViewUp = camera.viewUp || [0, 1, 0];

  // 计算旋转后的viewUp向量（这才是正确的相对旋转）
  const newViewUp: [number, number, number] = [
    currentViewUp[0] * Math.cos(ninetyDegreesRadians) -
    currentViewUp[1] * Math.sin(ninetyDegreesRadians),
    currentViewUp[0] * Math.sin(ninetyDegreesRadians) +
    currentViewUp[1] * Math.cos(ninetyDegreesRadians),
    0,
  ];

  // 设置新的相机参数
  viewport.setCamera({
    ...camera,
    viewUp: newViewUp,
    rotation: newRotation % 360, // 确保角度在0-359范围内
  });

  viewport.render();
  console.log('Rotating Image Clockwise 90°');
}

export function ResetImage(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // Implement the logic to reset the image
  // Resets the viewport's camera
  viewport.resetCamera();
  // Resets the viewport's properties
  viewport.resetProperties();
  viewport.render();
  console.log('Resetting Image');
}

export function InvertImage(currentViewportId: string): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // Implement the logic to invert the image
  const invert = !viewport.getProperties().invert;
  viewport.setProperties({ invert });
  viewport.render();
  console.log('Inverting Image');
}

export function setOriginalSize(currentViewportId: string) {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // 1) 先正常 fit（或本来就是 fit 状态）
  viewport.resetCamera();

  // 2) 计算“fit → 1:1”的放大倍数
  const { dimensions, spacing } = viewport.getImageData();
  console.log(`dimensions:${dimensions}, spacing:${spacing}`);
  const canvas = viewport.canvas;

  // 水平方向 1:1 需要的倍率
  const cssPixelsPerDicomPx = canvas.clientWidth / (dimensions[0] * spacing[0]);
  // 垂直方向 1:1 需要的倍率
  const cssPixelsPerDicomPy =
    canvas.clientHeight / (dimensions[1] * spacing[1]);
  // 取两者最小值，保证整张图不会被裁剪
  const zoomFactor = Math.min(cssPixelsPerDicomPx, cssPixelsPerDicomPy);
  console.log(`zoomFactor:${zoomFactor}`);
  console.log(
    `canvas.clientWidth:${canvas.clientWidth}, dimensions[0]:${dimensions[0]}, spacing[0]:${spacing[0]}`
  );
  console.log(
    `canvas.clientHeight:${canvas.clientHeight}, dimensions[1]:${dimensions[1]}, spacing[1]:${spacing[1]}`
  );
  // 3) 直接放大
  const zoom = viewport.getZoom();
  viewport.setZoom((zoom * 1) / zoomFactor);
  viewport.render();
}

export function activateMagnifier(currentViewportId: string) {
  console.log('Activating Magnifier');
  const toolGroup = getToolgroupByViewportId(currentViewportId);
  const isActive =
    toolGroup.getActivePrimaryMouseButtonTool() === MagnifyTool.toolName;
  if (isActive) {
    toolGroup.setToolPassive(MagnifyTool.toolName, {
      removeAllBindings: true,
    });
  } else {
    toolGroup.setToolActive(MagnifyTool.toolName, {
      bindings: [
        {
          mouseButton: MouseBindings.Primary, // Left Click
        },
      ],
    });
  }
}

export function invertContrast(currentViewportId: string) {
  const viewport =
    cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
  const targetBool = !viewport.getProperties().invert;
  viewport.setProperties({
    invert: targetBool,
  });
  viewport.render();
}

export function rotateAnyAngle(currentViewportId: string) {
  const toolGroup = getToolgroupByViewportId(currentViewportId);
  const planar = toolGroup.getToolInstance(PlanarRotateTool.toolName); // Reset rotation angle
  const isActive = planar.mode === csToolsEnums.ToolModes.Active;
  console.log(
    `PlanarRotateTool is currently ${isActive ? 'active' : 'inactive'}`
  );
  if (isActive) {
    toolGroup.setToolPassive(PlanarRotateTool.toolName, {
      removeAllBindings: true,
    });
  } else {
    toolGroup.setToolActive(PlanarRotateTool.toolName, {
      bindings: [
        {
          mouseButton: MouseBindings.Primary, // Left Click
        },
      ],
    });
  }
  console.log('Rotating Image by Any Angle');
}

// ==================== 线段测量相关函数 ====================

/**
 * 激活线段测量工具
 */
export function activateLengthMeasurement(viewportId: string): boolean {
  console.log(
    `[activateLengthMeasurement] Activating length measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateLengthTool(viewportId);
}

/**
 * 停用线段测量工具
 */
export function deactivateLengthMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateLengthMeasurement] Deactivating length measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateLengthTool(viewportId);
}

/**
 * 切换线段测量工具状态
 */
export function toggleLengthMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleLengthMeasurement] Toggling length measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleLengthTool(viewportId);
}

/**
 * 清除线段测量标注
 */
export function clearLengthMeasurements(viewportId: string): boolean {
  console.log(
    `[clearLengthMeasurements] Clearing length measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearLengthMeasurements(viewportId);
}

/**
 * 获取线段测量结果
 */
// eslint-disable-next-line
export function getLengthMeasurements(viewportId: string): any[] {
  console.log(
    `[getLengthMeasurements] Getting length measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getLengthMeasurements(viewportId);
}

/**
 * 检查线段测量工具是否激活
 */
export function isLengthMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isLengthToolActive(viewportId);
}

// ==================== 角度测量相关函数 ====================

/**
 * 激活角度测量工具
 */
export function activateAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[activateAngleMeasurement] Activating angle measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateAngleTool(viewportId);
}

/**
 * 停用角度测量工具
 */
export function deactivateAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateAngleMeasurement] Deactivating angle measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateAngleTool(viewportId);
}

/**
 * 切换角度测量工具状态
 */
export function toggleAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleAngleMeasurement] Toggling angle measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleAngleTool(viewportId);
}

/**
 * 清除角度测量标注
 */
export function clearAngleMeasurements(viewportId: string): boolean {
  console.log(
    `[clearAngleMeasurements] Clearing angle measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearAngleMeasurements(viewportId);
}

/**
 * 获取角度测量结果
 */
// eslint-disable-next-line
export function getAngleMeasurements(viewportId: string): any[] {
  console.log(
    `[getAngleMeasurements] Getting angle measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getAngleMeasurements(viewportId);
}

/**
 * 检查角度测量工具是否激活
 */
export function isAngleMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isAngleToolActive(viewportId);
}

// ==================== 胫骨平台夹角测量相关函数 ====================

/**
 * 激活胫骨平台夹角测量工具
 */
export function activateTibialPlateauAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[activateTibialPlateauAngleMeasurement] Activating TPA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateTibialPlateauAngleTool(viewportId);
}

/**
 * 停用胫骨平台夹角测量工具
 */
export function deactivateTibialPlateauAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateTibialPlateauAngleMeasurement] Deactivating TPA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateTibialPlateauAngleTool(viewportId);
}

/**
 * 切换胫骨平台夹角测量工具状态
 */
export function toggleTibialPlateauAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleTibialPlateauAngleMeasurement] Toggling TPA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleTibialPlateauAngleTool(viewportId);
}

/**
 * 清除胫骨平台夹角测量标注
 */
export function clearTibialPlateauAngleMeasurements(viewportId: string): boolean {
  console.log(
    `[clearTibialPlateauAngleMeasurements] Clearing TPA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearTibialPlateauAngleMeasurements(viewportId);
}

/**
 * 获取胫骨平台夹角测量结果
 */
// eslint-disable-next-line
export function getTibialPlateauAngleMeasurements(viewportId: string): any[] {
  console.log(
    `[getTibialPlateauAngleMeasurements] Getting TPA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getTibialPlateauAngleMeasurements(viewportId);
}

/**
 * 检查胫骨平台夹角测量工具是否激活
 */
export function isTibialPlateauAngleMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isTibialPlateauAngleToolActive(viewportId);
}

// ==================== 髋臼水平角测量相关函数 ====================

/**
 * 激活髋臼水平角测量工具
 */
export function activateDARAMeasurement(viewportId: string): boolean {
  console.log(
    `[activateDARAMeasurement] Activating DARA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateDARAMeasurementTool(viewportId);
}

/**
 * 停用髋臼水平角测量工具
 */
export function deactivateDARAMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateDARAMeasurement] Deactivating DARA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateDARAMeasurementTool(viewportId);
}

/**
 * 切换髋臼水平角测量工具状态
 */
export function toggleDARAMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleDARAMeasurement] Toggling DARA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleDARAMeasurementTool(viewportId);
}

/**
 * 清除髋臼水平角测量标注
 */
export function clearDARAMeasurements(viewportId: string): boolean {
  console.log(
    `[clearDARAMeasurements] Clearing DARA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearDARAMeasurements(viewportId);
}

/**
 * 获取髋臼水平角测量结果
 */
// eslint-disable-next-line
export function getDARAMeasurements(viewportId: string): any[] {
  console.log(
    `[getDARAMeasurements] Getting DARA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getDARAMeasurements(viewportId);
}

/**
 * 检查髋臼水平角测量工具是否激活
 */
export function isDARAMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isDARAMeasurementToolActive(viewportId);
}

// ==================== 髋关节牵引指数测量相关函数 ====================

/**
 * 激活髋关节牵引指数测量工具
 */
export function activateHipDIMeasurement(viewportId: string): boolean {
  console.log(
    `[activateHipDIMeasurement] Activating HipDI measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateHipDIMeasurementTool(viewportId);
}

/**
 * 停用髋关节牵引指数测量工具
 */
export function deactivateHipDIMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateHipDIMeasurement] Deactivating HipDI measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateHipDIMeasurementTool(viewportId);
}

/**
 * 切换髋关节牵引指数测量工具状态
 */
export function toggleHipDIMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleHipDIMeasurement] Toggling HipDI measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleHipDIMeasurementTool(viewportId);
}

/**
 * 清除髋关节牵引指数测量标注
 */
export function clearHipDIMeasurements(viewportId: string): boolean {
  console.log(
    `[clearHipDIMeasurements] Clearing HipDI measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearHipDIMeasurements(viewportId);
}

/**
 * 获取髋关节牵引指数测量结果
 */
// eslint-disable-next-line
export function getHipDIMeasurements(viewportId: string): any[] {
  console.log(
    `[getHipDIMeasurements] Getting HipDI measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getHipDIMeasurements(viewportId);
}

/**
 * 检查髋关节牵引指数测量工具是否激活
 */
export function isHipDIMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isHipDIMeasurementToolActive(viewportId);
}

// ==================== 髋关节水平角测量相关函数 ====================

/**
 * 激活髋关节水平角测量工具
 */
export function activateHipNHAAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[activateHipNHAAngleMeasurement] Activating HipNHA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateHipNHAAngleMeasurementTool(viewportId);
}

/**
 * 停用髋关节水平角测量工具
 */
export function deactivateHipNHAAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateHipNHAAngleMeasurement] Deactivating HipNHA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateHipNHAAngleMeasurementTool(viewportId);
}

/**
 * 切换髋关节水平角测量工具状态
 */
export function toggleHipNHAAngleMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleHipNHAAngleMeasurement] Toggling HipNHA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleHipNHAAngleMeasurementTool(viewportId);
}

/**
 * 清除髋关节水平角测量标注
 */
export function clearHipNHAAngleMeasurements(viewportId: string): boolean {
  console.log(
    `[clearHipNHAAngleMeasurements] Clearing HipNHA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearHipNHAAngleMeasurements(viewportId);
}

/**
 * 获取髋关节水平角测量结果
 */
// eslint-disable-next-line
export function getHipNHAAngleMeasurements(viewportId: string): any[] {
  console.log(
    `[getHipNHAAngleMeasurements] Getting HipNHA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getHipNHAAngleMeasurements(viewportId);
}

/**
 * 检查髋关节水平角测量工具是否激活
 */
export function isHipNHAAngleMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isHipNHAAngleMeasurementToolActive(viewportId);
}

// ==================== TPLO测量相关函数 ====================

/**
 * 激活TPLO测量工具
 */
export function activateTPLOMeasurement(viewportId: string): boolean {
  console.log(
    `[activateTPLOMeasurement] Activating TPLO measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateTPLOMeasurementTool(viewportId);
}

/**
 * 停用TPLO测量工具
 */
export function deactivateTPLOMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateTPLOMeasurement] Deactivating TPLO measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateTPLOMeasurementTool(viewportId);
}

/**
 * 切换TPLO测量工具状态
 */
export function toggleTPLOMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleTPLOMeasurement] Toggling TPLO measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleTPLOMeasurementTool(viewportId);
}

/**
 * 清除TPLO测量标注
 */
export function clearTPLOMeasurements(viewportId: string): boolean {
  console.log(
    `[clearTPLOMeasurements] Clearing TPLO measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearTPLOMeasurements(viewportId);
}

/**
 * 获取TPLO测量结果
 */
// eslint-disable-next-line
export function getTPLOMeasurements(viewportId: string): any[] {
  console.log(
    `[getTPLOMeasurements] Getting TPLO measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getTPLOMeasurements(viewportId);
}

/**
 * 检查TPLO测量工具是否激活
 */
export function isTPLOMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isTPLOMeasurementToolActive(viewportId);
}

// ==================== TTA测量相关函数 ====================

/**
 * 激活TTA测量工具
 */
export function activateTTAMeasurement(viewportId: string): boolean {
  console.log(
    `[activateTTAMeasurement] Activating TTA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.activateTTAMeasurementTool(viewportId);
}

/**
 * 停用TTA测量工具
 */
export function deactivateTTAMeasurement(viewportId: string): boolean {
  console.log(
    `[deactivateTTAMeasurement] Deactivating TTA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.deactivateTTAMeasurementTool(viewportId);
}

/**
 * 切换TTA测量工具状态
 */
export function toggleTTAMeasurement(viewportId: string): boolean {
  console.log(
    `[toggleTTAMeasurement] Toggling TTA measurement for viewport: ${viewportId}`
  );
  return MeasurementToolManager.toggleTTAMeasurementTool(viewportId);
}

/**
 * 清除TTA测量标注
 */
export function clearTTAMeasurements(viewportId: string): boolean {
  console.log(
    `[clearTTAMeasurements] Clearing TTA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.clearTTAMeasurements(viewportId);
}

/**
 * 获取TTA测量结果
 */
// eslint-disable-next-line
export function getTTAMeasurements(viewportId: string): any[] {
  console.log(
    `[getTTAMeasurements] Getting TTA measurements for viewport: ${viewportId}`
  );
  return MeasurementToolManager.getTTAMeasurements(viewportId);
}

/**
 * 检查TTA测量工具是否激活
 */
export function isTTAMeasurementActive(viewportId: string): boolean {
  return MeasurementToolManager.isTTAMeasurementToolActive(viewportId);
}

// ==================== CBLO测量相关函数 ====================

export function activateCBLOMeasurement(viewportId: string): boolean {
  console.log(`[activateCBLOMeasurement] Activating CBLO measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateCBLOMeasurementTool(viewportId);
}

export function deactivateCBLOMeasurement(viewportId: string): boolean {
  console.log(`[deactivateCBLOMeasurement] Deactivating CBLO measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateCBLOMeasurementTool(viewportId);
}

export function clearCBLOMeasurements(viewportId: string): boolean {
  console.log(`[clearCBLOMeasurements] Clearing CBLO measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearCBLOMeasurements(viewportId);
}

// ==================== HipCoverage测量相关函数 ====================

export function activateHipCoverageMeasurement(viewportId: string): boolean {
  console.log(`[activateHipCoverageMeasurement] Activating HipCoverage measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateHipCoverageMeasurementTool(viewportId);
}

export function deactivateHipCoverageMeasurement(viewportId: string): boolean {
  console.log(`[deactivateHipCoverageMeasurement] Deactivating HipCoverage measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateHipCoverageMeasurementTool(viewportId);
}

export function clearHipCoverageMeasurements(viewportId: string): boolean {
  console.log(`[clearHipCoverageMeasurements] Clearing HipCoverage measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearHipCoverageMeasurements(viewportId);
}

// ==================== HipDorsalCoverage测量相关函数 ====================

export function activateHipDorsalCoverageMeasurement(viewportId: string): boolean {
  console.log(`[activateHipDorsalCoverageMeasurement] Activating HipDorsalCoverage measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateHipDorsalCoverageTool(viewportId);
}

export function deactivateHipDorsalCoverageMeasurement(viewportId: string): boolean {
  console.log(`[deactivateHipDorsalCoverageMeasurement] Deactivating HipDorsalCoverage measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateHipDorsalCoverageTool(viewportId);
}

export function clearHipDorsalCoverageMeasurements(viewportId: string): boolean {
  console.log(`[clearHipDorsalCoverageMeasurements] Clearing HipDorsalCoverage measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearHipDorsalCoverageMeasurements(viewportId);
}

// ==================== 找圆心测量相关函数 ====================

export function activateCircleCenterMeasurement(viewportId: string): boolean {
  console.log(`[activateCircleCenterMeasurement] Activating CircleCenter measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateCircleCenterMeasurementTool(viewportId);
}

export function deactivateCircleCenterMeasurement(viewportId: string): boolean {
  console.log(`[deactivateCircleCenterMeasurement] Deactivating CircleCenter measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateCircleCenterMeasurementTool(viewportId);
}

export function clearCircleCenterMeasurements(viewportId: string): boolean {
  console.log(`[clearCircleCenterMeasurements] Clearing CircleCenter measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearCircleCenterMeasurements(viewportId);
}

// ==================== 找中线测量相关函数 ====================

export function activateMidlineMeasurement(viewportId: string): boolean {
  console.log(`[activateMidlineMeasurement] Activating Midline measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateMidlineMeasurementTool(viewportId);
}

export function deactivateMidlineMeasurement(viewportId: string): boolean {
  console.log(`[deactivateMidlineMeasurement] Deactivating Midline measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateMidlineMeasurementTool(viewportId);
}

export function clearMidlineMeasurements(viewportId: string): boolean {
  console.log(`[clearMidlineMeasurements] Clearing Midline measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearMidlineMeasurements(viewportId);
}

// ==================== 找中点测量相关函数 ====================

export function activateFindMidpointMeasurement(viewportId: string): boolean {
  console.log(`[activateFindMidpointMeasurement] Activating FindMidpoint measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateFindMidpointMeasurementTool(viewportId);
}

export function deactivateFindMidpointMeasurement(viewportId: string): boolean {
  console.log(`[deactivateFindMidpointMeasurement] Deactivating FindMidpoint measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateFindMidpointMeasurementTool(viewportId);
}

export function clearFindMidpointMeasurements(viewportId: string): boolean {
  console.log(`[clearFindMidpointMeasurements] Clearing FindMidpoint measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearFindMidpointMeasurements(viewportId);
}

// ==================== 直线垂直倾斜度测量相关函数 ====================

export function activateVerticalTiltMeasurement(viewportId: string): boolean {
  console.log(`[activateVerticalTiltMeasurement] Activating VerticalTilt measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateVerticalTiltMeasurementTool(viewportId);
}

export function deactivateVerticalTiltMeasurement(viewportId: string): boolean {
  console.log(`[deactivateVerticalTiltMeasurement] Deactivating VerticalTilt measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateVerticalTiltMeasurementTool(viewportId);
}

export function clearVerticalTiltMeasurements(viewportId: string): boolean {
  console.log(`[clearVerticalTiltMeasurements] Clearing VerticalTilt measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearVerticalTiltMeasurements(viewportId);
}

// ==================== 直线水平倾斜度测量相关函数 ====================

export function activateHorizontalTiltMeasurement(viewportId: string): boolean {
  console.log(`[activateHorizontalTiltMeasurement] Activating HorizontalTilt measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activateHorizontalTiltMeasurementTool(viewportId);
}

export function deactivateHorizontalTiltMeasurement(viewportId: string): boolean {
  console.log(`[deactivateHorizontalTiltMeasurement] Deactivating HorizontalTilt measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivateHorizontalTiltMeasurementTool(viewportId);
}

export function clearHorizontalTiltMeasurements(viewportId: string): boolean {
  console.log(`[clearHorizontalTiltMeasurements] Clearing HorizontalTilt measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearHorizontalTiltMeasurements(viewportId);
}

// ==================== 多边形长度测量相关函数 ====================

/**
 * 激活多边形长度测量工具
 */
export function activatePolygonLengthMeasurement(viewportId: string): boolean {
  console.log(`[activatePolygonLengthMeasurement] Activating PolygonLength measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activatePolygonLengthMeasurementTool(viewportId);
}

/**
 * 停用多边形长度测量工具
 */
export function deactivatePolygonLengthMeasurement(viewportId: string): boolean {
  console.log(`[deactivatePolygonLengthMeasurement] Deactivating PolygonLength measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivatePolygonLengthMeasurementTool(viewportId);
}

/**
 * 清除多边形长度测量标注
 */
export function clearPolygonLengthMeasurements(viewportId: string): boolean {
  console.log(`[clearPolygonLengthMeasurements] Clearing PolygonLength measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearPolygonLengthMeasurements(viewportId);
}

// ==================== 拆线长度测量相关函数 ====================

/**
 * 激活拆线长度测量工具
 */
export function activatePolylineLengthMeasurement(viewportId: string): boolean {
  console.log(`[activatePolylineLengthMeasurement] Activating PolylineLength measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.activatePolylineLengthMeasurementTool(viewportId);
}

/**
 * 停用拆线长度测量工具
 */
export function deactivatePolylineLengthMeasurement(viewportId: string): boolean {
  console.log(`[deactivatePolylineLengthMeasurement] Deactivating PolylineLength measurement for viewport: ${viewportId}`);
  return MeasurementToolManager.deactivatePolylineLengthMeasurementTool(viewportId);
}

/**
 * 清除拆线长度测量标注
 */
export function clearPolylineLengthMeasurements(viewportId: string): boolean {
  console.log(`[clearPolylineLengthMeasurements] Clearing PolylineLength measurements for viewport: ${viewportId}`);
  return MeasurementToolManager.clearPolylineLengthMeasurements(viewportId);
}
export class ImageLoadError extends Error {
  constructor(message: string, failedImageIds: string[]) {
    super(message);
    this.name = 'ImageLoadError';
    this.failedImageIds = failedImageIds; // 附加失败 ID 列表
  }
  failedImageIds: string[];
}

/**
 * 安全的图像栈设置函数，带超时保护和错误捕获
 * @param viewport - Cornerstone viewport 实例
 * @param imageIds - 图像 ID 数组
 * @param imageIndex - 当前图像索引
 * @param timeout - 超时时间（毫秒），默认30秒
 */
export async function safeSetStack(
  viewport: any,
  imageIds: string[],
  imageIndex: number,
  timeout: number = 30000
): Promise<void> {
  const errors: string[] = [];

  // 错误事件处理器
  const handler = (evt: any) => {
    console.error(`捕获到图像加载错误: ${evt.detail.imageId}`);
    errors.push(evt.detail.imageId);
  };

  // 添加错误监听器
  eventTarget.addEventListener(EVENTS.IMAGE_LOAD_ERROR, handler);

  try {
    // 创建超时 Promise
    const timeoutPromise = new Promise<never>((_, reject) => {
      setTimeout(() => {
        reject(new Error(`图像加载超时 (${timeout}ms)`));
      }, timeout);
    });

    // 等待 setStack 完成或超时
    await Promise.race([
      viewport.setStack(imageIds, imageIndex),
      timeoutPromise
    ]);

    // setStack 完成后，检查是否有错误
    if (errors.length > 0) {
      throw new ImageLoadError(
        `图像加载失败：共 ${errors.length} 张（${errors.join(', ')}）`,
        errors
      );
    }

    console.log(`✅ 图像栈设置成功: ${imageIds.length} 张图像`);
  } finally {
    // 无论成功失败，都移除监听器（清理资源）
    eventTarget.removeEventListener(EVENTS.IMAGE_LOAD_ERROR, handler);
  }
}

const StackViewer = ({
  imageIndex = 0,
  imageUrls = [],
  viewportId,
  renderingEngineId,
  selected
}: {
  imageIndex?: number;
  imageUrls?: string[];
  viewportId: string;
  renderingEngineId: string;
  selected?: boolean;
}) => {
  const elementRef = useRef<HTMLDivElement>(null);
  // 用于捕获异步错误并在渲染时抛出，让 Error Boundary 能够捕获
  const [renderError, setRenderError] = React.useState<Error | null>(null);
  // 获取overlay启用状态
  const overlayEnabled = useSelector(selectOverlayEnabled);
  // const action = useSelector((state: RootState) => state.functionArea.action);
  // const dispatch = useDispatch();

  // 监听overlay状态变化，启用/禁用DicomOverlayTool
  useEffect(() => {
    try {
      const toolGroup = MeasurementToolManager.getToolGroup(viewportId);
      // const toolGroup = ToolGroupManager.getToolGroup(`STACK_TOOL_GROUP_ID_${viewportId}`);
      if (!toolGroup) {
        console.warn(`[StackViewer] Tool group not found for viewport: ${viewportId}`);
        return;
      }

      if (overlayEnabled) {
        console.log(`[StackViewer] Enabling DicomOverlay for viewport: ${viewportId}`);
        toolGroup.setToolEnabled(DicomOverlayTool.toolName);
      } else {
        console.log(`[StackViewer] Disabling DicomOverlay for viewport: ${viewportId}`);
        toolGroup.setToolDisabled(DicomOverlayTool.toolName);
        //再次启用，表示关闭四角信息
        toolGroup.setToolEnabled(DicomOverlayTool.toolName);
      }
    } catch (error) {
      console.error(`[StackViewer] Error toggling DicomOverlay:`, error);
    }
  }, [overlayEnabled, viewportId]);

  // // 监听imageUrls变化并重新加载图像
  // useEffect(() => {
  //   const renderingEngine = cornerstone.getRenderingEngine(renderingEngineId);
  //   if (!renderingEngine) {
  //     return;
  //   }

  //   const viewport = renderingEngine.getViewport(viewportId) as cornerstone.Types.IStackViewport;
  //   if (viewport && imageUrls.length > 0) {
  //     console.log(`[StackViewer] imageUrls changed for viewport ${viewportId}, reloading...`);
  //     viewport.setStack(imageUrls, imageIndex).then(() => {
  //       viewport.render();
  //     }).catch((error) => {
  //       console.error('[StackViewer] Error reloading image stack:', error);
  //     });
  //   }
  // }, [imageUrls, imageIndex, viewportId, renderingEngineId]);

  useEffect(() => {
    const setup = async () => {
      // 清除之前的错误状态（如果有）
      setRenderError(null);

      // // 初始化 Cornerstone
      // cornerstone.init();
      // cornerstoneTools.init();
      // const state = store.getState();
      // console.log(`当前系统模式：${state.systemMode.mode}`);

      // const token =
      //   state.systemMode.mode === SystemMode.Emergency
      //     ? state.product.guest
      //     : state.userInfo.token;
      // console.log(`token stack.image.viewer: ${token}`);

      // cornerstoneDICOMImageLoader.init({
      //   maxWebWorkers: navigator.hardwareConcurrency || 1,
      //   errorInterceptor: (error) => {
      //     if (error.status === 401) {
      //       console.error('Authentication failed. Please refresh the token.');
      //     }
      //     console.error(`请求dcm文件出错:${error}`);
      //   },
      //   beforeSend: (xhr, imageId, defaultHeaders) => {
      //     return {
      //       ...defaultHeaders,
      //       Authorization: `Bearer ${token}`,
      //       Language: 'en',
      //       Product: 'DROS',
      //       Source: 'Electron',
      //     };
      //   },
      // });
      // const currentViewportId = viewportId;
      eventTarget.addEventListener(
        cornerstoneTools.Enums.Events.ANNOTATION_COMPLETED,
        (evt) => {
          const { annotation } = evt.detail;
          console.log('Annotation completed event:', annotation);
          if (annotation.metadata.toolName === 'LinearSplineROI') {
            console.log('SplineROITool annotation completed:', annotation);
            overlayRedRectangle(viewportId);
            //取消工具激活状态
            const toolGroup = ToolGroupManager.getToolGroup(
              'STACK_TOOL_GROUP_ID'
            );
            if (!toolGroup) {
              console.log('toolGroup not found');
            }
            toolGroup?.setToolPassive('LinearSplineROI', {
              removeAllBindings: true,
            });
          }
        }
      );
      const viewportInput: cornerstone.Types.PublicViewportInput = {
        viewportId,
        element: elementRef.current!,
        type: cornerstone.Enums.ViewportType.STACK,
      };
      const renderingEngine = cornerstone.getRenderingEngine(renderingEngineId);
      if (!renderingEngine) {
        console.error(
          `[stack.image.viewer] No rendering engine with id ${renderingEngineId} found`
        );
        return;
      }
      // Enable the element for use with Cornerstone
      renderingEngine.enableElement(viewportInput);
      registerTools(viewportId, renderingEngine.id);

      // Get the stack viewport that was created
      const viewport = renderingEngine.getViewport(
        viewportId
      ) as cornerstone.Types.IStackViewport;

      // 增强的图像加载逻辑，包含完善的错误处理
      try {
        console.log(`重新加载图像----开始`);
        console.log(`图像URLs:`, imageUrls);
        console.log(`图像索引:`, imageIndex);

        // 1. 验证图像URLs
        if (!imageUrls || imageUrls.length === 0) {
          throw new Error('图像URL列表为空');
        }

        // 2. 验证图像索引
        if (imageIndex < 0 || imageIndex >= imageUrls.length) {
          throw new Error(`图像索引无效: ${imageIndex}, 有效范围: 0-${imageUrls.length - 1}`);
        }

        // 3. 预检查图像可访问性（可选）
        // await validateImageUrls(imageUrls);

        // 4. 设置图像栈，包含超时保护
        await safeSetStack(viewport, imageUrls, imageIndex);

        // 5. 图像加载完成后，自动应用保持宽高比的适应
        fitImageWithAspectRatio(viewportId);

        console.log(`重新加载图像----结束`);

      } catch (error) {

        // 不直接抛出错误，而是保存到状态中
        // 在下次渲染时抛出，这样 Error Boundary 才能捕获
        const enhancedError = enhanceError(error, { imageUrls, imageIndex, viewportId });
        setRenderError(enhancedError);
        return; // 不再继续执行后续代码
        // 根据错误严重程度决定处理策略
        if (isCriticalError(enhancedError)) {
          // 严重错误：保存到状态，让 Error Boundary 处理
          console.error('🚨 严重图像加载错误，将在渲染时抛出给 Error Boundary:', enhancedError);
          setRenderError(enhancedError);
          return; // 不再继续执行后续代码
        } else {
          // 非严重错误：仅记录日志，继续运行
          console.warn('⚠️ 图像加载警告:', enhancedError);
          // 可以在这里尝试降级策略，比如显示占位符
        }
      }
      viewport.render();
    };

    setup();
  }, [elementRef, imageIndex, viewportId, renderingEngineId, imageUrls[0]]);

  // 监听容器大小变化，自动保持宽高比
  useEffect(() => {
    if (!elementRef.current) return;

    // 创建防抖的适应函数
    const debouncedFit = debounce(() => {
      // console.log(`容器大小变化了---------`)
      requestAnimationFrame(() => {
        fitImageWithAspectRatio(viewportId);
      });

    }, 100);

    // 创建ResizeObserver监听容器大小变化
    const resizeObserver = new ResizeObserver(debouncedFit);
    resizeObserver.observe(elementRef.current);

    console.log(`[StackViewer] ResizeObserver attached to viewport: ${viewportId}`);

    // 清理函数
    return () => {
      resizeObserver.disconnect();
      console.log(`[StackViewer] ResizeObserver disconnected from viewport: ${viewportId}`);
    };
  }, [viewportId]);

  // 在渲染期间检查错误状态，如果有错误则抛出
  // 这样 Error Boundary 就能捕获到异步错误了
  if (renderError) {
    throw renderError;
  }

  return (
    <div
      id={viewportId}
      ref={elementRef}
      onContextMenu={(e) => e.preventDefault()}
      style={{
        width: '100%', height: '100%', backgroundColor: '#000',
        border: selected
          ? '2px solid blue'
          : '1px solid gray',
      }}
    />
  );
};

/**
 * 带错误边界的 StackViewer 包装组件
 * 自动处理图像加载错误，提供优雅的错误恢复机制
 */
export const StackViewerWithErrorBoundary = ({
  imageIndex = 0,
  imageUrls = [],
  viewportId,
  renderingEngineId,
  selected,
  maxRetries = 3,
  onError
}: {
  imageIndex?: number;
  imageUrls?: string[];
  viewportId: string;
  renderingEngineId: string;
  selected?: boolean;
  maxRetries?: number;
  onError?: (error: Error, errorInfo: any) => void;
}) => {
  return (
    <ImageViewerErrorBoundary
      maxRetries={maxRetries}
      onError={onError}
    >
      <StackViewer
        imageIndex={imageIndex}
        imageUrls={imageUrls}
        viewportId={viewportId}
        renderingEngineId={renderingEngineId}
        selected={selected}
      />
    </ImageViewerErrorBoundary>
  );
};

export default StackViewer;
