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 * as cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
import { useSelector } from 'react-redux';
import { RootState } from '@/states/store';
import { SystemMode } from '@/states/systemModeSlice';
import store from '@/states/store';
import { clearAction } from '@/states/view/functionAreaSlice';
import { useDispatch } from 'react-redux';
import { SplineROITool } from '@cornerstonejs/tools';
import { eventTarget } from '@cornerstonejs/core';

const {
  MagnifyTool,
  PanTool,
  WindowLevelTool,
  StackScrollTool,
  ZoomTool,
  LabelTool,
  ToolGroupManager,
  Enums: csToolsEnums,
  PlanarRotateTool,
} = cornerstoneTools;
const { MouseBindings } = csToolsEnums;
let toolGroup: cornerstoneTools.Types.IToolGroup;
let currentViewportId: string;

function overlayRedRectangle() {
  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
}

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();
      //取消工具激活状态
      const toolGroup = ToolGroupManager.getToolGroup('STACK_TOOL_GROUP_ID');
      if (!toolGroup) {
        console.log('toolGroup not found');
      }
      toolGroup?.setToolPassive('LinearSplineROI', { removeAllBindings: true });
    }
  }
);

function registerTools(viewportId, renderingEngineId) {
  // Add tools to Cornerstone3D
  cornerstoneTools.addTool(MagnifyTool);
  cornerstoneTools.addTool(PanTool);
  cornerstoneTools.addTool(WindowLevelTool);
  cornerstoneTools.addTool(StackScrollTool);
  cornerstoneTools.addTool(ZoomTool);
  cornerstoneTools.addTool(LabelTool);
  cornerstoneTools.addTool(PlanarRotateTool);
  // Define a tool group
  const toolGroupId = 'STACK_TOOL_GROUP_ID';
  const toolGroupTmp = ToolGroupManager.createToolGroup(toolGroupId);
  if (!toolGroupTmp) {
    return;
  }
  toolGroup = toolGroupTmp;
  // Add tools to the tool group
  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);

  // Set the LabelTool as active
  // toolGroup.setToolActive(LabelTool.toolName, {
  //   bindings: [
  //     {
  //       mouseButton: MouseBindings.Primary, // Left Click
  //     },
  //   ],
  // });
  // Set the initial state of the tools
  // toolGroup.setToolActive(WindowLevelTool.toolName, {
  //   bindings: [
  //     {
  //       mouseButton: MouseBindings.Primary, // Left Click
  //     },
  //   ],
  // });

  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.addViewport(viewportId, renderingEngineId);
}
function addLMark(): void {
  // Implement the logic to add an L mark
  console.log('Adding L Mark');
  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);
}
function addRLabel(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 });
}

function adjustBrightnessAndContrast() {
  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
        },
      ],
    });
  }
}

function fitImageSize() {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  viewport.resetCamera();
  viewport.render();
}

function deleteSelectedMark(): void {
  const viewport =
    cornerstone.getEnabledElementByViewportId(currentViewportId).viewport;
  const allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();
  for (const annotation of allAnnotations) {
    if (annotation.data.text === 'L' || annotation.data.text === 'R') {
      cornerstoneTools.annotation.state.removeAnnotation(
        annotation.annotationUID!
      );
    }
  }
  viewport.render();
}

function addMask(): void {
  // Implement the logic to add a mask
  console.log('Adding Mask');
  // Add the specific logic to add a mask here
  cornerstoneTools.addTool(SplineROITool);
  toolGroup.addTool(SplineROITool.toolName);
  toolGroup.addToolInstance('LinearSplineROI', SplineROITool.toolName, {
    spline: {
      type: SplineROITool.SplineTypes.Linear,
    },
  });
  toolGroup.setToolActive('LinearSplineROI', {
    bindings: [{ mouseButton: MouseBindings.Primary }],
  });
}
function HorizontalFlip(): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // 切换水平翻转状态
  const { flipHorizontal } = viewport.getCamera();
  viewport.setCamera({ flipHorizontal: !flipHorizontal });
  console.log('Flipping Image Horizontally');
}

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

function ApplyColormap(): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // Implement the logic to apply colormap
  viewport.setProperties({ colormap: { name: 'hsv' } });
  viewport.render();
  console.log('Applying Colormap');
}

function RotateCounterclockwise90(): void {
  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
    .viewport as cornerstone.StackViewport;
  // let { rotation } = viewport.getViewPresentation();
  // const currentRotataion = viewport.getRotation();
  // viewport.rotation(22)
  // console.log(`rotation:${rotation}`)
  // if(!!rotation){
  //   rotation=0;
  // }
  // viewport.setViewPresentation({ rotation: rotation ?? 0 + 30 });
  // // // Implement the logic to rotate the image counterclockwise
  // // viewport.setCamera({ rotation: -90 });
  // viewport.render();

  // // 1. 获取当前的视图表现状态（一个完整的对象）
  // const currentViewPresentation = viewport.getViewPresentation();

  // // 2. 创建一个新的对象，基于当前状态，只更新你需要修改的属性
  // // 使用展开运算符 (...) 来复制所有现有属性
  // const newViewPresentation = {
  //   ...currentViewPresentation, // 保留所有原有属性，如 scale, translation, flip 等
  //   rotation: currentViewPresentation.rotation ?? + 30, // 只覆盖 rotation 属性
  // };

  // // 3. 将完整的新状态对象设置回 viewport
  // viewport.setViewPresentation(newViewPresentation);
  // viewport.render();

  //----------------------------------------
  // // 获取当前的完整视图状态
  // const currentViewState = viewport.getViewPresentation();

  // // 创建新的视图状态对象，保持所有其他属性不变
  // const newViewState = {
  //   ...currentViewState, // 保留所有现有属性
  //   rotation: (currentViewState.rotation ?? 0 + 30) % 360 // 只修改rotation
  // };

  // // 设置新的视图状态
  // viewport.setViewPresentation(newViewState);
  // viewport.render();
  //-----------------------------------------
  // 获取当前相机
  const camera = viewport.getCamera();

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

  // // 转换为弧度
  // const radians = newRotation * Math.PI / 180;

  // // 计算新的viewUp向量（顺时针旋转90度）
  // const newViewUp:[number, number, number] = [
  //   Math.cos(radians),  // X分量
  //   Math.sin(radians),  // Y分量
  //   0                   // Z分量
  // ];

  // // 设置新的相机参数
  // viewport.setCamera({
  //   ...camera,          // 保持其他相机参数不变
  //   viewUp: newViewUp,  // 更新向上向量
  //   rotation: newRotation // 更新旋转角度（可选，但推荐）
  // });

  // 计算新的旋转角度（当前角度 + 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°');
}

function RotateClockwise90(): 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°');
}

function ResetImage(): 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');
}

function InvertImage(): 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');
}

function setOriginalSize(viewport) {
  // 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();
}

const StackViewer = ({
  imageIndex = 0,
  imageUrls = [],
}: {
  imageIndex?: number;
  imageUrls?: string[];
}) => {
  const elementRef = useRef<HTMLDivElement>(null);
  const action = useSelector((state: RootState) => state.functionArea.action);
  const dispatch = useDispatch();

  useEffect(() => {
    const setup = async () => {
      // 初始化 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',
          };
        },
      });

      // Instantiate a rendering engine
      const renderingEngineId = 'myRenderingEngine';
      const renderingEngine = new cornerstone.RenderingEngine(
        renderingEngineId
      );

      const viewportId = 'CT_AXIAL_STACK';
      currentViewportId = viewportId;
      const viewportInput: cornerstone.Types.PublicViewportInput = {
        viewportId,
        element: elementRef.current!,
        type: cornerstone.Enums.ViewportType.STACK,
      };

      renderingEngine.enableElement(viewportInput);
      registerTools(viewportId, renderingEngineId);

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

      // 给定一个dcm文件路径，加载并显示出来
      try {
        await viewport.setStack(imageUrls, imageIndex);
      } catch (error) {
        if (error instanceof Error) {
          console.error(
            '[stack.image.viewer] Error setting image stack:',
            error.message
          );
        } else {
          console.error('[stack.image.viewer] Unknown error:', error);
        }
      }
      viewport.render();
    };

    setup();
  }, [elementRef, imageIndex]);

  useEffect(() => {
    if (action) {
      // Handle the action
      switch (action) {
        case 'Add L Mark':
          addLMark();
          break;
        case 'Add R Mark':
          // Implement the logic to add an R mark
          addRLabel(currentViewportId);
          console.log('Adding R Mark');
          break;
        case 'Delete Selected Mark': {
          deleteSelectedMark();
          break;
        }
        case 'Horizontal Flip': {
          HorizontalFlip();
          break;
        }
        case 'Vertical Flip': {
          VerticalFlip();
          break;
        }
        case 'Rotate Counterclockwise 90': {
          RotateCounterclockwise90();
          break;
        }
        case 'Rotate Clockwise 90':
          RotateClockwise90();
          break;
        case 'Rotate Any Angle':
          // Implement the logic to rotate the image by any angle
          {
            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');
          }
          break;
        case 'Crop Image':
          addMask();
          break;
        case 'Delete Digital Mask':
          // Implement the logic to delete the digital mask
          console.log('Deleting Digital Mask');
          break;
        case 'Adjust Brightness and Contrast':
          adjustBrightnessAndContrast();
          break;
        case 'Crop Selected Area':
          // Implement the logic to crop the selected area
          console.log('Cropping Selected Area');
          break;
        case 'Delete Mask':
          // Implement the logic to delete the mask
          console.log('Deleting Mask');
          break;
        case 'Image Comparison':
          // Implement the logic for image comparison
          console.log('Comparing Images');
          break;
        case 'Invert Contrast':
          // Implement the logic to invert the contrast
          {
            const viewport =
              cornerstone.getEnabledElementByViewportId(
                currentViewportId
              ).viewport;
            const targetBool = !viewport.getProperties().invert;
            viewport.setProperties({
              invert: targetBool,
            });
            viewport.render();
          }
          console.log('Inverting Contrast');
          break;
        case '1x1 Layout':
          // Implement the logic for 1x1 layout
          console.log('Setting 1x1 Layout');
          break;
        case '1x2 Layout':
          // Implement the logic for 1x2 layout
          console.log('Setting 1x2 Layout');
          break;
        case '2x2 Layout':
          // Implement the logic for 2x2 layout
          console.log('Setting 2x2 Layout');
          break;
        case '4x4 Layout':
          // Implement the logic for 4x4 layout
          console.log('Setting 4x4 Layout');
          break;
        case 'Magnifier': {
          // Implement the logic for magnifier
          console.log('Activating Magnifier');
          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
                },
              ],
            });
          }

          break;
        }
        case 'Fit Size': {
          // Implement the logic to fit the image size
          fitImageSize();
          console.log('Fitting Image Size');
          break;
        }
        case 'Original Size': {
          // Implement the logic to set the image to original size
          console.log('Setting Image to Original Size');
          setOriginalSize(
            cornerstone.getEnabledElementByViewportId(currentViewportId)
              .viewport as cornerstone.StackViewport
          );
          break;
        }
        case 'Zoom Image':
          // Implement the logic to zoom the image
          console.log('Zooming Image');
          break;
        case 'Reset Cursor':
          // Implement the logic to reset the cursor
          console.log('Resetting Cursor');
          break;
        case 'Pan':
          // Implement the logic to pan the image
          console.log('Panning Image');
          break;
        case 'Invert Image':
          InvertImage();
          break;
        case 'Reset Image':
          ResetImage();
          break;
        case 'Snapshot':
          // Implement the logic to take a snapshot
          console.log('Taking Snapshot');
          break;
        case 'Advanced Processing':
          // Implement the logic for advanced processing
          console.log('Performing Advanced Processing');
          break;
        case 'Musician':
          // Implement the logic for musician
          console.log('Activating Musician');
          break;
        case 'Image Measurement':
          // Implement the logic for image measurement
          console.log('Measuring Image');
          break;
        case 'More':
          // Implement the logic for more options
          console.log('Showing More Options');
          break;
        case 'Apply Colormap':
          ApplyColormap();
          break;
        default:
          break;
      }
      dispatch(clearAction()); //清理后可连续同一个action触发响应
    }
  }, [action]);

  return (
    <div
      ref={elementRef}
      style={{ width: '100%', height: '100%', backgroundColor: '#000' }}
    />
  );
};

export default StackViewer;
