// 文档地址：https://hoteamsoft.feishu.cn/docx/doxcnIGUt6E02WAD0fkeC46Omtg
import { useHttp } from '@crami/http';
import { getInfo, ICP_CONFIG } from '@/utils/commMethods';
import { message } from '@crami/ui';
import { watch, watchEffect } from 'vue';
import { getUuid } from '@/utils/uuid';
import { debounce } from 'lodash-es';

// 编码器type
export const HB_ENCODER = 'HBEncoder';
// 编码器类型type
export const HB_MODEL_SELECT = 'HBModelSelect';

export const judgeExistHbEncoder = formMethods => {
  if (!formMethods) return false;
  const formSchemas = formMethods.getFormSchemas();
  if (!formSchemas || !formSchemas.length) return false;

  const encoderItem = formSchemas.find(schema => schema.type === HB_ENCODER);
  if (!encoderItem) return false;

  return true;
};

const encoderRequest = async (formMethods, mode = 'cancel') => {
  if (!formMethods) return true;
  const formSchemas = formMethods.getFormSchemas();
  if (!formSchemas || !formSchemas.length) return true;

  const encoderItem = formSchemas.find(schema => schema.type === HB_ENCODER);
  if (!encoderItem) return true;

  const modelSelectItem = formSchemas.find(schema => schema.type === HB_MODEL_SELECT);
  const formData = formMethods.getData();

  let code = '';
  switch (mode) {
    case 'cancel':
      break;
    case 'save':
      code = formData[encoderItem.name];
    default:
      break;
  }
  const userInfo = getInfo(ICP_CONFIG);

  let result = false;
  await useHttp({
    url: '/api/codegenerator/codeGenerator/updateState',
    method: 'post',
    params: {
      stateId: 'APPLIED',
      companyId: userInfo.companyId,
      connect: userInfo.connect,
      lang: userInfo.lang,
      // 编码值
      code,
      // 模型名
      objectType: modelSelectItem ? formData[modelSelectItem.name] : encoderItem.modelName,
      // 模型的字段名
      property: encoderItem.name,
      // form会话id
      pageSessionId: encoderItem?.fieldProps?.pageSessionId,
    },
  })
    .then(res => {
      if (res.code === 200) {
        mode === 'save' && (result = true);
      } else {
        message.warning(res.msg);
      }
    })
    .catch(err => {
      message.warning(err);
    });

  return result;
};

export default encoderRequest;

const ifClickCloseIcon = e => {
  let level = 0;
  let currentNode = e.target || e.srcElement;
  const CLOSE_CLS = 'ant-modal-close';
  while (level++ <= 5 && currentNode) {
    if (currentNode?.classList?.contains(CLOSE_CLS)) {
      break;
    }
    currentNode = currentNode.parentNode;
  }
  if (!currentNode?.classList?.contains(CLOSE_CLS)) {
    return;
  }

  return currentNode;
};

const transferSelector = selector => {
  if (!selector) return;

  if (!['#', '.'].includes(selector.slice(0, 1))) {
    selector = `#${selector}`;
  }

  return selector;
};

const ifBelongModal = (selector, node) => {
  if (!selector) return;

  const modal = document.querySelector(selector);
  if (!modal || !modal.contains(node)) {
    return;
  }
  return true;
};

const ifBelongForm = (selector, node) => {
  if (!selector) return;

  const form = document.querySelector(selector);
  if (!form) {
    return;
  }

  let modal;
  let level = 0;
  while (level++ <= 5 && node) {
    if (node?.classList.contains('ant-modal')) {
      modal = node;
      break;
    }
    node = node.parentNode;
  }
  if (!modal || !modal.contains(form)) {
    return;
  }

  return true;
};

interface ConfigInterface {
  // modal样式选择器
  modalSelector?: string;
  // form样式选择器
  formSelector?: string;
  delay?: number;
}

const ifClickModalCloseIcon = (e, config: ConfigInterface) => {
  const closeNode = ifClickCloseIcon(e);
  if (!closeNode) return;

  const { modalSelector, formSelector } = config;
  return ifBelongModal(modalSelector, closeNode) || ifBelongForm(formSelector, closeNode);
};

// 硬编码弹窗点击关闭按钮处理
export const monitorHandleClose = (formRef, config: ConfigInterface = {}) => {
  const delay = config.delay || 0;

  if (!config.modalSelector && !config.formSelector) return;

  config.modalSelector = transferSelector(config.modalSelector);
  config.formSelector = transferSelector(config.formSelector);

  const handleCloseEvent = (e: EventTarget) => {
    if (!ifClickModalCloseIcon(e, config)) return;
    const methods = formRef.value;
    encoderRequest(methods);
  };

  let observer;
  const observerTarget = () => {
    observer = new IntersectionObserver(entries => {
      const entry = entries[0];
      entry.isIntersecting
        ? document.addEventListener('click', handleCloseEvent)
        : setTimeout(() => {
            document.removeEventListener('click', handleCloseEvent);
          }, delay);
    });

    // 延迟监测确保dom渲染后才observe
    setTimeout(() => {
      const target = document.querySelector(config.modalSelector || config.formSelector);
      target && observer?.observe(target);
    }, delay);
  };
  const unObserverTarget = () => {
    observer?.unobserve(document.querySelector(config.modalSelector || config.formSelector));
    observer = null;
  };

  watch(
    formRef,
    val => {
      const handler = val ? observerTarget : unObserverTarget;
      handler();
    },
    { immediate: true },
  );
};

// 添加会话id
export const registerEncoderSessionId = (formRef, options?: any) => {
  // 会话id关联form，确保sessionId唯一
  if (formRef.value && !formRef.value._sessionId) {
    formRef.value._sessionId = getUuid(16, 16);
  }

  const handleSessionId = () => {
    const formSchemas = formRef.value?.getFormSchemas();

    if (formSchemas && formSchemas.length) {
      const encoderItem = formSchemas.find(schema => schema.type === HB_ENCODER);
      if (!encoderItem) return;

      // 编码器组件已存在会话id时不处理
      if (encoderItem?.fieldProps?.pageSessionId) return;

      const dataIndex = encoderItem.name;
      formRef.value.updateSchema([
        {
          dataIndex,
          fieldProps: {
            pageSessionId: formRef?.value?._sessionId,
          },
        },
      ]);
      ifInited = true;

      // 添加需要持续监听的选项
      // !options.constant && destroyWatch();
    }
  };

  let ifInited = false;
  // 通过watchEffect监听，表单项修改值也会触发监听，使用防抖处理
  const debounceHandler = debounce(handleSessionId, 300, { leading: false });

  // 会有编码器组件因为级联关系而使用和不使用的特殊情况，一直监听确保formSchemas变动时能处理
  watchEffect(() => {
    // 这步为了触发watchEffect依赖收集，保证后续执行
    formRef?.value?.getFormSchemas();
    debounceHandler();
  });
};
