import type { MesProBagCodeApi } from '#/api/mes/pro/bagCode';

import { onBeforeUnmount, ref } from 'vue';

import { message } from 'ant-design-vue';

import {
  cancelBagCodeGenerateTask,
  getBagCodeGenerateTask,
} from '#/api/mes/pro/bagCode';

/** 弹窗最小接口，避免依赖内部 ModalApi 类型 */
interface GenerateModalApi {
  close: () => Promise<void>;
  setState: (state: {
    showCancelButton?: boolean;
    showConfirmButton?: boolean;
  }) => unknown;
}

interface GenerateTaskCallbacks {
  /** 生成成功（状态 30），调用方刷新列表 */
  onSuccess: () => void;
  /** 生成失败（状态 50），调用方更换幂等键后允许重新提交 */
  onFailed?: () => void;
}

/** 终态：已完成 / 已取消 / 已失败 */
const FINAL_STATUSES = new Set([30, 40, 50]);

export function isFinalTaskStatus(status?: number) {
  return status !== undefined && FINAL_STATUSES.has(status);
}

/**
 * 大批量袋码后台生成：轮询进度、取消任务，并把弹窗按钮切换为进度展示态。
 */
export function useGenerateTask(
  modalApi: GenerateModalApi,
  callbacks: GenerateTaskCallbacks,
) {
  const task = ref<MesProBagCodeApi.GenerateTask>();
  const canceling = ref(false);
  let timer: ReturnType<typeof setTimeout> | undefined;

  function stopPolling() {
    if (timer) clearTimeout(timer);
    timer = undefined;
  }

  function restoreButtons() {
    modalApi.setState({ showConfirmButton: true, showCancelButton: true });
  }

  /** 重置到可编辑态：关闭弹窗、重新打开、失败重试前调用 */
  function reset() {
    stopPolling();
    task.value = undefined;
    canceling.value = false;
    restoreButtons();
  }

  /** 进入进度展示态：隐藏提交/取消按钮，进度区自行提供取消操作 */
  function start(initial: MesProBagCodeApi.GenerateTask) {
    stopPolling();
    task.value = initial;
    modalApi.setState({ showConfirmButton: false, showCancelButton: false });
    void refresh();
  }

  async function refresh() {
    if (!task.value) return;
    stopPolling();
    try {
      const current = await getBagCodeGenerateTask(task.value.id);
      task.value = current;
      if (isFinalTaskStatus(current.status)) {
        finish(current);
        return;
      }
    } catch {
      // 一次查询失败不终止轮询，避免网络抖动把进度卡死
    }
    timer = setTimeout(refresh, 2000);
  }

  function finish(current: MesProBagCodeApi.GenerateTask) {
    if (current.status === 30) {
      message.success(
        `生成完成：共 ${current.totalCount ?? 0} 条袋码` +
          (current.palletCount
            ? `，并自动生成 ${current.palletCount} 个托盘`
            : ''),
      );
      callbacks.onSuccess();
      void modalApi.close();
      return;
    }
    if (current.status === 40) {
      message.info('生成任务已取消，已生成的数据已清理');
      void modalApi.close();
      return;
    }
    // 失败：回到可编辑态，由调用方更换 requestId 后重新提交
    message.error(current.errorMsg ?? '生成失败，请重新提交');
    task.value = undefined;
    restoreButtons();
    callbacks.onFailed?.();
  }

  async function cancel() {
    if (!task.value || canceling.value) return;
    canceling.value = true;
    try {
      await cancelBagCodeGenerateTask(task.value.id);
      message.info('已申请取消，正在停止并清理已生成数据');
    } catch {
      message.error('取消生成失败，请稍后重试');
    } finally {
      canceling.value = false;
    }
  }

  onBeforeUnmount(stopPolling);

  return {
    task,
    canceling,
    cancel,
    reset,
    stopPolling,
    start,
  };
}
