import type { Ref } from 'vue';
import { ref, watch } from 'vue';

export interface FloatPanelAnchorsAutoHeightOptions {
  height: Ref<number>;
  measuredContentHeight: Ref<number>;
  panelHeaderHeight: Ref<number>;
  closable: () => boolean;
  full: () => boolean;
  maxContainerHeight: () => number;
  autoHeight: () => boolean;
  setAnchors: (values: number | number[], reset?: boolean) => void;
  setHeight: (contentHeight: number, updateAnchor?: boolean) => void;
}

/**
 * 边界锚点 + 默认锚点合并，以及 autoHeight 与测量联动。
 * 与关闭动画、`isClosing` 无关。
 */
export function useFloatPanelAnchorsAutoHeight(options: FloatPanelAnchorsAutoHeightOptions) {
  const {
    height,
    measuredContentHeight,
    panelHeaderHeight,
    closable,
    full,
    maxContainerHeight,
    autoHeight,
    setAnchors,
    setHeight,
  } = options;

  /** 区分「首次从 0 按内容撑起」与「用户已关到 0 勿再被测量顶开」 */
  const autoHeightSyncedOnce = ref(false);

  /** 在 setHeight 之后收敛锚点：仅保留 0 / max / 当前总高，去掉默认 100 等残留 */
  function replaceAnchorsAfterContentHeight(total: number) {
    const list = new Set<number>([total]);
    if (closable()) list.add(0);
    if (full()) list.add(maxContainerHeight());
    setAnchors(
      [...list].filter((v) => v <= maxContainerHeight()).sort((a, b) => a - b),
      true,
    );
  }

  /** 未改 height 时仅补充边界锚点（合并，不整表替换） */
  function mergeBoundaryAnchors() {
    const b: number[] = [];
    if (closable()) b.push(0);
    if (full()) b.push(maxContainerHeight());
    if (!b.length) return;
    setAnchors(b.length === 1 ? b[0]! : b, false);
  }

  watch(
    [
      () => closable(),
      () => full(),
      () => maxContainerHeight(),
      measuredContentHeight,
      panelHeaderHeight,
      () => autoHeight(),
    ],
    () => {
      const boundary = new Set<number>();
      if (closable()) boundary.add(0);
      if (full()) boundary.add(maxContainerHeight());

      if (!autoHeight()) {
        const defaultAnchors = [100, innerHeight * 0.6];
        setAnchors([...new Set([...boundary, ...defaultAnchors])], false);
        autoHeightSyncedOnce.value = false;
        return;
      }

      // autoHeight：不使用 100 / 60% 视口等默认锚点，避免打开时被吸附到最小非零锚点
      const ch = measuredContentHeight.value;
      if (ch <= 0) return;

      const header = panelHeaderHeight.value;
      const maxContent = Math.max(0, maxContainerHeight() - header);
      const contentClamped = Math.min(ch, maxContent);
      const targetPanel = contentClamped + header;

      if (height.value === 0) {
        if (!autoHeightSyncedOnce.value) {
          setHeight(contentClamped, true);
          replaceAnchorsAfterContentHeight(targetPanel);
          autoHeightSyncedOnce.value = true;
        }
        return;
      }

      autoHeightSyncedOnce.value = true;
      if (Math.abs(height.value - targetPanel) > 0.5) {
        setHeight(contentClamped, true);
        replaceAnchorsAfterContentHeight(targetPanel);
      } else {
        mergeBoundaryAnchors();
      }
    },
    { flush: 'post', immediate: true },
  );

  /** 供外层对 `height` 的 watch 调用：从关闭态再次打开时允许 autoHeight 重新同步 */
  function resetAutoHeightSyncOnReopen(prev: number | undefined, h: number) {
    if (prev === 0 && h !== 0) {
      autoHeightSyncedOnce.value = false;
    }
  }

  return {
    autoHeightSyncedOnce,
    resetAutoHeightSyncOnReopen,
  };
}
