import {
  calculateTextExprValue,
  condition,
  getRealResponse,
  handleSuccessMessage,
} from '../util/util';
import isPlainObject from 'lodash/isPlainObject';
import isFunction from 'lodash/isFunction'
import { request as requestInstance } from 'cn-request';
import { formUrlencoded } from '@/common/util/const';
import qs from 'query-string';
import { CnMessage, CnDialog } from '@cainiaofe/cn-ui-m';
import {
  getButtonListByPosition,
  getButtonPrototypeListByPosition,
} from '@/common/manager/button';
import { getJSExpressionPrototype } from '@/common/manager/common-style';
import { getJSXTemplate } from '@/common/manager/setter-snippet';

export const __urlParams__ = '__urlParams__';
export const __record__ = '__record__';
export const __ds__ = '__ds__';
export const __blank__ = '__blank__';

export const createRequestSuccessPrototype = (position, config) => {
  const { afterRequestCondition } = config || {};
  const buttonList = getButtonListByPosition(position);
  const buttonPrototypeList = getButtonPrototypeListByPosition(position);
  const configure = [
    {
      name: 'optType',
      title: '请求成功后',
      display: 'inline',
      setter: {
        componentName: 'CnSelectSetter',
        props: {
          options: buttonList,
          selectProps: {
            hasClear: true,
          },
        },
      },
    },
  ];
  if (buttonPrototypeList?.length > 0) {
    configure.push({
      name: 'options',
      display: 'plain',
      title: '按钮配置项',
      setter: {
        componentName: 'ObjectSetter',
        props: {
          config: {
            items: [...buttonPrototypeList],
          },
        },
      },
    });
  }
  const result = {
    name: 'afterRequest',
    title: '请求成功后',
    display: 'plain',
    setter: {
      componentName: 'ObjectSetter',
      props: {
        config: {
          items: configure,
        },
      },
    },
  };
  if (afterRequestCondition) {
    result.condition = afterRequestCondition;
  }
  return result;
};

export function handleRequestParams(params, config = {}) {
  let result = {};
  const { flexibleParams = false } = config;
  if (params && params.length > 0) {
    params.forEach((item) => {
      if (item) {
        const { label, value } = item;
        if (label && value !== undefined) {
          result[label] = calculateTextExprValue(value, config);
        }
      }
    });
  } else if (typeof params === 'function') {
    const temp = calculateTextExprValue(params, config);
    if (isPlainObject(temp) || (isFunction(temp) && flexibleParams)) {
      result = temp;
    }
  }
  return result;
}

export function makeRequest(config) {
  const { needSuccessToast = true } = config;
  const {
    handleParams,
    buttonConfig,
    record,
    state,
    recordDataSource,
    urlParamsDataSource,
    onCancel,
    extraParamList,
    isDesign,
    position = '',
    noNeedHandleResult,
    _context,
    getExtraParam,
  } = config;
  return new Promise((resolve, reject) => {
    if (buttonConfig) {
      const { options = {} } = buttonConfig;
      const {
        requestConfig,
        needConfirm,
        confirmInfo = {},
        afterRequest,
      } = options;
      const sendRequest = () => {
        const realUrl = requestConfig?.url;
        if (realUrl) {
          requestInstance(
            transRequestConfigToRemote({
              requestConfig,
              handleParams,
              state,
              urlParamsDataSource,
              recordDataSource,
              isDesign,
              extraParamList,
              getExtraParam,
            }),
          )
            .then((res) => {
              let result = getRealResponse(res);
              if (!noNeedHandleResult) {
                result = handleResultProcessFunc2(res, requestConfig, {
                  state,
                });
              }
              const { success, errorCode, errorMsg } = result;
              if (success) {
                if (afterRequest?.optType) {
                }

                resolve(result);
                if (needSuccessToast) {
                  handleSuccessMessage(result);
                }
              } else {
                reject(result);
                CnMessage.error(
                  errorMsg || errorCode || `${requestConfig?.url} 请求异常`,
                );
              }
            })
            .catch((err) => {
              reject(err);
            });
        }
      };
      if (needConfirm) {
        const title = calculateTextExprValue(confirmInfo.title, {
          urlParamsDataSource,
          recordDataSource,
          state,
          extraParamList,
        });
        const content = calculateTextExprValue(confirmInfo.content, {
          urlParamsDataSource,
          recordDataSource,
          state,
          extraParamList,
        });

        CnDialog.confirm({
          title: title || '通知',
          content: content || '',
          messageProps: {
            className: 'l2-dialog-message-content',
          },
          onOk: () => {
            sendRequest();
          },
          onCancel: () => {
            onCancel && onCancel();
          },
          onClose: (reason) => {
            if (reason !== 'ok') {
              onCancel && onCancel();
            }
          },
          // cancelProps: {
          //   // children: '关闭弹窗',
          // },
        });
      } else {
        sendRequest();
      }
    }
  });
}

export const createServiceSelectPrototype = (config) => {
  const {
    optType,
    paramSetter,
    position,
    paramSelectSetter,
    jsExpressionSetter,
    paramTitleDom,
    dynamicUrlTemplate,
  } = config || {};
  let confirmShowType;
  const hoverTip = [];
  const configure = [
    {
      name: 'requestConfig',
      title: '查询服务',
      display: 'inline',
      setter: {
        componentName: 'ServiceChoiceSetter',
        props: {
          paramTitleDom,
          buttonText: '选择请求API',
          params: {
            env: 'pre',
            pageSize: 999,
            // serviceType: 'HSF',
          },
          paramSetter,
          dynamicUrlTemplate,
        },
      },
      condition(prop) {
        return condition(prop, optType, 'optType');
      },
    },
    {
      name: 'needConfirm',
      title: '二次确认',
      display: 'inline',
      setter: {
        componentName: 'BoolSetter',
      },
      condition(prop) {
        return condition(prop, optType, 'optType');
      },
    },
    {
      name: 'confirmInfo',
      display: 'plain',
      title: '按钮配置项',
      condition(prop) {
        return condition(prop, optType, 'optType');
      },
      setter: {
        componentName: 'ObjectSetter',
        props: {
          config: {
            items: [
              {
                name: 'title',
                title: '二次确认标题',
                display: 'inline',
                // setter: {
                //   componentName: 'StringSetter',
                // },
                setter: {
                  componentName: 'MixedSetter',
                  props: {
                    setters: [
                      {
                        componentName: 'CnI18nSetter',
                        title: '字符串',
                      },
                      paramSelectSetter,
                      jsExpressionSetter ||
                      getJSExpressionPrototype({
                        type: 'tableRequest',
                      }),
                    ],
                  },
                },
                condition(prop) {
                  return condition(prop, true, 'needConfirm');
                },
              },
              {
                name: 'content',
                title: '二次确认内容',
                display: 'inline',
                // setter: {
                //   componentName: 'TextAreaSetter',
                // },
                setter: {
                  componentName: 'MixedSetter',
                  props: {
                    setters: [
                      {
                        componentName: 'CnI18nSetter',
                        title: '字符串',
                      },
                      paramSelectSetter,
                      jsExpressionSetter ||
                      getJSExpressionPrototype({
                        type: 'tableRequest',
                      }),
                      getJSXTemplate({ position }),
                    ],
                  },
                },
                condition(prop) {
                  return condition(prop, true, 'needConfirm');
                },
              },
              confirmShowType,
            ],
          },
        },
      },
    },
  ];
  return configure;
};

export function transRequestConfigToRemote(config = {}) {
  const {
    requestConfig,
    handleParams,
    isDesign,
    urlParamsDataSource,
    recordDataSource,
    state,
    extraParamList,
    getExtraParam,
    formatParam,
    needFormatResult,
  } = config;
  if (requestConfig) {
    const realUrl = requestConfig?.url;
    const {
      url,
      params = [],
      serviceType,
      method,
      contentType,
    } = requestConfig;
    const temp = {
      url,
      method: 'post',
      data: {},
    };
    if (realUrl) {
      temp.url = realUrl;
    }
    if (serviceType === 'http') {
      temp.withCredentials = true;
    }
    if (typeof handleParams === 'function') {
      temp.data = handleParams(temp.data);
    }

    const realParams = handleRequestParams(params, {
      urlParamsDataSource,
      recordDataSource,
      state,
      extraParamList,
      getExtraParam,
      flexibleParams: true,
    });
    if (typeof realParams === 'function') {
      temp.data = realParams();
    } else if (Object.keys(realParams).length > 0) {
      temp.data = { ...temp.data, ...realParams };
    }

    if (serviceType === 'http') {
      if (method) {
        temp.method = method;
      }
      if (contentType === formUrlencoded) {
        temp.headers = {
          'content-type': contentType,
        };
        if (temp.method === 'post' && isPlainObject(temp.data)) {
          temp.data = qs.stringify(temp.data);
        }
      }
    }
    if (temp.method === 'get') {
      temp.params = temp.data;
      delete temp.data;
    }
    if (formatParam) {
      temp.formatParam = formatParam;
    }
    if (needFormatResult === true) {
      temp.formatResult = handleResultProcessFunc(requestConfig);
    }
    return temp;
  } else {
    return {};
  }
}

export function handleResultProcessFunc(requestConfig) {
  if (requestConfig) {
    const { resultProcessFunc, serviceType, mockData } = requestConfig;
    if (typeof resultProcessFunc === 'function') {
      return (res, state) => {
        let newRes = getRealResponse(res);
        try {
          const temp = resultProcessFunc(newRes, state);
          if (temp && temp.data && temp.success !== undefined) {
            newRes = temp.data;
          } else {
            newRes = temp;
          }
        } catch (e) {
          console.error('请求结果回调执行失败', e);
        }
        return newRes;
      };
    } else if (serviceType === 'mock' && isPlainObject(mockData)) {
      return () => {
        return mockData?.data;
      };
    } else {
      return (res) => {
        if (res?.data) {
          return res.data;
        }
        return res;
      };
    }
  }
}

export function handleResultProcessFunc2(response, requestConfig, extra) {
  const { state } = extra || {};
  let newRes = getRealResponse(response);
  if (requestConfig) {
    const { resultProcessFunc, serviceType, mockData } = requestConfig;
    if (
      typeof resultProcessFunc === 'function' &&
      (serviceType === 'mokelay' || serviceType === 'http')
    ) {
      try {
        if (isPlainObject(state)) {
          newRes = resultProcessFunc(newRes, state);
        } else {
          newRes = resultProcessFunc(newRes);
        }
      } catch (e) {
        console.error('请求结果回调执行失败', e);
      }
      return newRes;
    } else if (serviceType === 'mock' && isPlainObject(mockData)) {
      return mockData;
    }
  }
  return newRes;
}
