import { ref } from 'vue';

export interface FloatingImageItem {
  id: string;
  src: string;
}

export interface FloatingWindowState {
  id: string;
  src: string;
  activeImageId: string;
  imageList: FloatingImageItem[];
  activeIndex: number;
  x: number;
  y: number;
  width: number;
  height: number;
  zIndex: number;
  zoom: number;
  rotate: number;
  imgOffsetX: number;
  imgOffsetY: number;
}

interface OpenImageParams {
  imageId: string;
  src: string;
  imageList: FloatingImageItem[];
}

export const useFloatingImageManager = () => {
  const windows = ref<FloatingWindowState[]>([]);

  const getNextWindowZIndex = () => {
    return windows.value.length > 0
      ? Math.max(...windows.value.map((item) => item.zIndex)) + 1
      : 10001;
  };

  const normalizeImageList = ({ imageId, src, imageList }: OpenImageParams) => {
    const validImageList = imageList.filter((item) => item.id && item.src);
    const currentImage = validImageList.find((item) => item.id === imageId);

    if (currentImage) {
      return validImageList;
    }

    return [
      {
        id: imageId,
        src,
      },
      ...validImageList,
    ];
  };

  const getActiveIndex = (imageId: string, imageList: FloatingImageItem[]) => {
    const targetIndex = imageList.findIndex((item) => item.id === imageId);
    return targetIndex >= 0 ? targetIndex : 0;
  };

  const openImage = ({ imageId, src, imageList }: OpenImageParams) => {
    const nextImageList = normalizeImageList({ imageId, src, imageList });
    const activeIndex = getActiveIndex(imageId, nextImageList);

    windows.value = (() => {
      const existing = windows.value.find((item) => item.id === imageId);
      const nextZIndex = getNextWindowZIndex();

      if (existing) {
        const targetZIndex = existing.zIndex === nextZIndex - 1
          ? existing.zIndex
          : nextZIndex;

        return windows.value.map((item) =>
          item.id === imageId
            ? {
              ...item,
              src,
              activeImageId: nextImageList[activeIndex]?.id ?? imageId,
              imageList: nextImageList,
              activeIndex,
              zIndex: targetZIndex,
            }
            : item,
        );
      }

      const winWidth = 680;
      const winHeight = 580;
      const offsetSeed = windows.value.length % 5;
      const nextX = Math.max(
        0,
        (window.innerWidth - winWidth) / 2 + offsetSeed * 30,
      );
      const nextY = Math.max(
        0,
        (window.innerHeight - winHeight) / 2 + offsetSeed * 30,
      );

      return [
        ...windows.value,
        {
          id: imageId,
          src,
          activeImageId: nextImageList[activeIndex]?.id ?? imageId,
          imageList: nextImageList,
          activeIndex,
          x: nextX,
          y: nextY,
          width: winWidth,
          height: winHeight,
          zIndex: nextZIndex,
          zoom: 1,
          rotate: 0,
          imgOffsetX: 0,
          imgOffsetY: 0,
        },
      ];
    })();
  };

  const closeWindow = (id: string) => {
    windows.value = windows.value.filter((item) => item.id !== id);
  };

  const bringToFront = (id: string) => {
    const maxZIndex =
      windows.value.length > 0
        ? Math.max(...windows.value.map((item) => item.zIndex))
        : 10000;
    const target = windows.value.find((item) => item.id === id);

    if (!target || target.zIndex === maxZIndex) {
      return;
    }

    windows.value = windows.value.map((item) =>
      item.id === id
        ? {
          ...item,
          zIndex: maxZIndex + 1,
        }
        : item,
    );
  };

  const updateWindow = (id: string, patch: Partial<FloatingWindowState>) => {
    windows.value = windows.value.map((item) =>
      item.id === id
        ? {
          ...item,
          ...patch,
        }
        : item,
    );
  };

  return {
    windows,
    openImage,
    closeWindow,
    bringToFront,
    updateWindow,
  };
};
