import { CnDialog, CnMessage } from '@cainiaofe/cn-ui';
import { request as requestInstance } from 'cn-request';
import get from 'lodash/get';
import {
  calculateRequestExecute,
  calculateTextExprValue,
  condition,
  executeObjectExpr,
  getRealRequestUrl,
  handleDesignMokelayUrl,
  handleSuccessMessage,
} from './util';
import {
  getButtonAction,
  getButtonListByPosition,
  getButtonPrototypeListByPosition,
} from '../manager/button';
import isPlainObject from 'lodash/isPlainObject';
import isFunction from 'lodash/isFunction'
import { getJSExpressionPrototype } from '../manager/common-style';
import { ButtonPosition } from '@/common/manager/position/button-position';
import {
  AfterRequestSuccess,
  formUrlencoded,
} from '@/common/util/const';
import qs from 'query-string';
import { getJSXTemplate } from '@/common/manager/setter-snippet';
import { __dataSource__ } from '@/common/util/expr-const';

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 const createServiceSelectPrototype = (config) => {
  const {
    optType,
    paramSetter,
    wholeParamSetter,
    position,
    paramSelectSetter,
    jsExpressionSetter,
    paramTitleDom,
    dynamicUrlTemplate,
  } = config || {};
  let confirmShowType;
  let hoverTip = [];
  if ([ButtonPosition.tableOperate].includes(position)) {
    confirmShowType = {
      name: 'confirmShowType',
      title: '二次确认展示效果',
      display: 'inline',
      setter: {
        componentName: 'RadioGroupSetter',
        props: {
          options: [
            { title: '弹窗（默认）', value: 'dialog' },
            { title: '气泡', value: 'balloon' },
          ],
        },
      },
      condition(prop) {
        return condition(prop, true, 'needConfirm');
      },
    };
  }
  // if([ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea].includes(position)) {
  //   hoverTip = [
  //     {
  //       name: 'needHover',
  //       title: '气泡提示',
  //       display: 'inline',
  //       setter: {
  //         componentName: 'BoolSetter',
  //       },
  //       condition(prop) {
  //         return condition(prop, optType, 'optType');
  //       },
  //     },
  //     {
  //       name: 'hoverInfo',
  //       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, 'needHover');
  //                 },
  //               },
  //               {
  //                 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, 'needHover');
  //                 },
  //               },
  //               confirmShowType,
  //             ],
  //           },
  //         },
  //       },
  //     },
  //   ]
  // }
  const configure = [
    {
      name: 'requestConfig',
      title: '查询服务',
      display: 'inline',
      setter: {
        componentName: 'ServiceChoiceSetter',
        props: {
          paramTitleDom,
          buttonText: '选择请求API',
          params: {
            env: 'pre',
            pageSize: 999,
            // serviceType: 'HSF',
          },
          paramSetter,
          wholeParamSetter,
          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,
            ],
          },
        },
      },
    },
    // ...hoverTip,
  ];
  if (
    [
      ButtonPosition.tableOperate,
      ButtonPosition.tableCell,
      ButtonPosition.tableToolArea,
    ].includes(position)
  ) {
    configure.push(
      createRequestSuccessPrototype(position + AfterRequestSuccess),
    );
  }

  if (position === ButtonPosition.tableOperate) {
    configure.push({
      name: 'keepPagination',
      title: '刷新表格时保留分页信息',
      setter: 'BoolSetter',
    });
  }

  return configure;
};

export function makeRequest(config) {
  let { 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 = getRealRequestUrl({
          requestConfig,
          state,
          extraParam: getExtraParam?.(),
        });
        if (realUrl) {
          const execute = calculateRequestExecute(
            requestConfig,
            {
              [__dataSource__]: state,
            },
            {},
            state,
          );
          if (execute === false) {
            reject();
            return;
          }
          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) {
                  const pos = position + AfterRequestSuccess;
                  const action = getButtonAction({
                    ...afterRequest,
                    position: pos,
                  });
                  if (action) {
                    needSuccessToast = false;
                    action?.({
                      position: pos,
                      urlParamsDataSource,
                      recordDataSource,
                      state,
                      buttonConfig: afterRequest,
                      response: result,
                      _context,
                    });
                  }
                }

                resolve(result);
                if (needSuccessToast) {
                  handleSuccessMessage(result);
                }
              } else {
                reject(result);
                if (!res?.hadShowErrorFeedback) {
                  CnMessage.error(errorMsg || errorCode || `${requestConfig?.url} 请求异常`);
                }
              }
            })
            .catch((err) => {
              reject(err);
              // const {errorCode, errorMsg } = err || {}
              // CnMessage.error(errorMsg || errorCode || `${requestConfig?.url} 请求异常`);
            });
        }
      };
      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();
            reject()
          },
          onClose: () => {
            onCancel && onCancel();
            reject()
          },
          // cancelProps: {
          //   // children: '关闭弹窗',
          // },
        });
      } else {
        sendRequest();
      }
    }
  });
}

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

    if (refreshDeps) {
      temp.refreshDeps = refreshDeps;
    }

    if (timeout) {
      temp.timeout = timeout;
    }

    if (isDesign && serviceType === 'mokelay') {
      temp.url = handleDesignMokelayUrl(temp.url);
    }
    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) &&
          !noQsStringifyFormatting
        ) {
          temp.data = qs.stringify(temp.data);
        }
      }
    }
    if (temp.method === 'get') {
      temp.params = temp.data;
      delete temp.data;
    }
    if (needFormatResult === true) {
      temp.formatResult = handleResultProcessFunc(requestConfig);
    }
    return temp;
  } else {
    return {};
  }
}

export function handleRequestParams(params, config: any = {}) {
  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 getRealResponse(res = {}) {
  const { status, data } = res;
  let result = res;
  if (status === 200 && data) {
    result = data;
  }
  return result;
}

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;
}
