/**
 * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
 * SPDX-License-Identifier: MIT
 */

import { useCallback, useEffect, useState } from 'react';

import {
  FlowNodeFormData,
  FormModelV2,
  FreeOperationType,
  HistoryService,
  TransformData,
  useCurrentEntity,
  usePlayground,
  useService,
} from '@flowgram.ai/free-layout-editor';

import { CommentEditorFormField } from '../constant';

export const useSize = () => {
  const node = useCurrentEntity();
  const nodeMeta = node.getNodeMeta();
  const playground = usePlayground();
  const historyService = useService(HistoryService);
  const { size = { width: 240, height: 150 } } = nodeMeta;
  const transform = node.getData(TransformData);
  const formModel = node.getData(FlowNodeFormData).getFormModel<FormModelV2>();
  const formSize = formModel.getValueIn<{ width: number; height: number }>(
    CommentEditorFormField.Size
  );

  const [width, setWidth] = useState(formSize?.width ?? size.width);
  const [height, setHeight] = useState(formSize?.height ?? size.height);

  // 初始化表单值
  useEffect(() => {
    const initSize = formModel.getValueIn<{ width: number; height: number }>(
      CommentEditorFormField.Size
    );
    if (!initSize) {
      formModel.setValueIn(CommentEditorFormField.Size, {
        width,
        height,
      });
    }
  }, [formModel, width, height]);

  // 同步表单外部值变化：初始化/undo/redo/协同
  useEffect(() => {
    const disposer = formModel.onFormValuesChange(({ name }) => {
      if (name !== CommentEditorFormField.Size) {
        return;
      }
      const newSize = formModel.getValueIn<{ width: number; height: number }>(
        CommentEditorFormField.Size
      );
      if (!newSize) {
        return;
      }
      setWidth(newSize.width);
      setHeight(newSize.height);
    });
    return () => disposer.dispose();
  }, [formModel]);

  const onResize = useCallback(() => {
    const resizeState = {
      width,
      height,
      originalWidth: width,
      originalHeight: height,
      positionX: transform.position.x,
      positionY: transform.position.y,
      offsetX: 0,
      offsetY: 0,
    };
    const resizing = (delta: { top: number; right: number; bottom: number; left: number }) => {
      if (!resizeState) {
        return;
      }

      const { zoom } = playground.config;

      const top = delta.top / zoom;
      const right = delta.right / zoom;
      const bottom = delta.bottom / zoom;
      const left = delta.left / zoom;

      const minWidth = 120;
      const minHeight = 80;

      const newWidth = Math.max(minWidth, resizeState.originalWidth + right - left);
      const newHeight = Math.max(minHeight, resizeState.originalHeight + bottom - top);

      // 如果宽度或高度小于最小值，则不更新偏移量
      const newOffsetX =
        (left > 0 || right < 0) && newWidth <= minWidth
          ? resizeState.offsetX
          : left / 2 + right / 2;
      const newOffsetY =
        (top > 0 || bottom < 0) && newHeight <= minHeight ? resizeState.offsetY : top;

      const newPositionX = resizeState.positionX + newOffsetX;
      const newPositionY = resizeState.positionY + newOffsetY;

      resizeState.width = newWidth;
      resizeState.height = newHeight;
      resizeState.offsetX = newOffsetX;
      resizeState.offsetY = newOffsetY;

      // 更新状态
      setWidth(newWidth);
      setHeight(newHeight);

      // 更新偏移量
      transform.update({
        position: {
          x: newPositionX,
          y: newPositionY,
        },
      });
    };

    const resizeEnd = () => {
      historyService.transact(() => {
        historyService.pushOperation(
          {
            type: FreeOperationType.dragNodes,
            value: {
              ids: [node.id],
              value: [
                {
                  x: resizeState.positionX + resizeState.offsetX,
                  y: resizeState.positionY + resizeState.offsetY,
                },
              ],
              oldValue: [
                {
                  x: resizeState.positionX,
                  y: resizeState.positionY,
                },
              ],
            },
          },
          {
            noApply: true,
          }
        );
        formModel.setValueIn(CommentEditorFormField.Size, {
          width: resizeState.width,
          height: resizeState.height,
        });
      });
    };

    return {
      resizing,
      resizeEnd,
    };
  }, [node, width, height, transform, playground, formModel, historyService]);

  return {
    width,
    height,
    onResize,
  };
};
