import { createVNode, inject } from 'vue';
import { NsMessage } from '../component/message';
import { NsModal } from '../component/modal';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { useRouter, useRoute } from 'vue-router';
import { cloneDeep, isBoolean, isEmpty, isFunction, isString, isUndefined } from 'lodash-es';
import { useParams } from '/nerv-lib/use/use-params';
import { usePath } from '/nerv-lib/use/use-path';
import { useApi } from '/nerv-lib/use/use-api';
import type { AxiosRequestConfig } from 'axios';
import { authorizationService } from '/nerv-base/store/modules/authorization-service';
import { stringUtil } from '/nerv-lib/util/string-util';
import { appConfigStore } from '/nerv-base/store/modules/app-config';
import { xlsxExport, xlsxImport } from '/nerv-lib/util/xlsx-util';

export interface Confirm {
  title: string; // 弹窗标题
  content: string; // 弹窗内容
  icon: string; //弹窗图标
  okButtonProps: object;
  okText: string; //确定按钮文本
}
export interface Action {
  label: string; //操作中文名
  name: string; //操作英文名
  openPermission?: boolean; // true则不鉴权
  checkApi?: string | Function | AxiosRequestConfig; // 检查api
  checkDynamicParams?: string | Array<string> | object; //check api传参 || url传参
  checkDefaultParams?: object; //check默认参数 固定值
  route?: string | Recordable; // 配置了路由则直接跳转
  confirm?: boolean | Confirm; //先弹窗再操作, true则使用默认显示方案
  showSuccess?: Boolean;
  api?: string | Function | AxiosRequestConfig; // 自动请求api
  dynamicParams?: string | Array<string> | object; //api传参 || url传参
  defaultParams?: object; //默认参数 固定值
  handle?: Function; //自定义回调，路由模式不触发
  finalHandle?: Function; //最终执行的函数
  ifShow?: boolean | Function; //显示依赖
  type?: string; //按钮 primary | ghost | dashed | link | text | default
  dynamicDisabled?: boolean | Function;
  isReload?: boolean;
  isClearCheck?: boolean; // 清空table选中行数据
  state?: String; // edit 为编辑态 其他为编辑中
  extra?: Recordable;
}

/**
 * step1:检测route，有则直接跳转。
 * step2:检测api，有则设置handle先行请求api，请求成功，有默认handle则执行。
 * step3:检测confirm，有则先弹窗，再执行step2
 */
interface actionParams {
  reload?: Function;
  clearCheck?: Function;
}
export function useAction(actionParams: actionParams = {}) {
  const router = useRouter();
  const route = useRoute();
  const { reload, clearCheck } = actionParams;
  const { getPath } = usePath();
  const { httpRequest } = useApi();
  const authService = authorizationService();
  const appConfig = appConfigStore();

  //todo 类型定义需简化
  const { tableEdit, tableSave, tableCancel, addRow, validate, getValue, getKey, tableDelete } =
    inject('tableEdit', {
      tableEdit: () => {},
      tableSave: () => {},
      tableCancel: () => {},
      addRow: () => {},
      validate: () => {},
      getValue: () => {},
      getKey: () => {},
      tableDelete: () => {},
    }) as {
      tableEdit: Function;
      tableSave: Function;
      tableCancel: Function;
      addRow: Function;
      validate: Function;
      getValue: Function;
      getKey: Function;
      tableDelete: Function;
    };

  function isIfShow(action: Action, data: any): boolean {
    const ifShow = action.ifShow;
    if (isBoolean(ifShow)) return ifShow;
    if (isFunction(ifShow)) return ifShow(data);
    return true;
  }

  function hasPermission(action: Action, data: any) {
    //todo 临时处理saas不鉴权
    if (__APP_INFO__.serviceMode === 'saas') {
      if (action.children) {
        return true;
      }
      if (action.openPermission) return true;

      return authService.checkAllPermission(action.name);
    }
    if (action.openPermission) return true;
    if (!appConfig.actionPermission) {
      return true;
    }
    if (isUndefined(route.name) || isUndefined(route.matched[0].name)) {
      console.error('route name is required');
    }
    const { projectName } = route.params;
    //处理IASSAction判断
    if (data && data.viewInfo && Array.isArray(data.viewInfo.actions)) {
      return data.viewInfo.actions.includes(action.name);
    } else {
      return authService.checkPermission(
        route.meta?.app ? route.meta?.app : (route.matched[0].name as string),
        route.meta?.bindView ? route.meta?.bindView : (route.name as string),
        stringUtil.firstToLower(
          action.name.replace(
            route.meta?.bindView ? route.meta?.bindView : (route.name as string),
            '',
          ),
        ),
        data.projectName || projectName,
      );
    }
  }

  function filterAction(action: Action, data: any) {
    const { state } = action;
    let stateShow = true;
    if (state && state !== 'add') {
      if (getValue(getKey(data))) {
        stateShow = state === 'edit' || isUndefined(state) ? false : true;
      } else {
        stateShow = state === 'edit' || isUndefined(state) ? true : false;
      }
    }

    return stateShow && hasPermission(action, data) && isIfShow(action, data);
  }

  function filterActionNoAuth(action: Action, data: any) {
    const { state } = action;
    let stateShow = true;
    if (state && state !== 'add') {
      if (getValue(getKey(data))) {
        stateShow = state === 'edit' || isUndefined(state) ? false : true;
      } else {
        stateShow = state === 'edit' || isUndefined(state) ? true : false;
      }
    }

    return stateShow && isIfShow(action, data);
  }

  function transformAction(action: Action, data: any) {
    const {
      label,
      name,
      state,
      route: toRoute,
      api,
      dynamicParams,
      defaultParams,
      showSuccess,
      confirm,
      checkApi,
      checkDynamicParams,
      checkDefaultParams,
      handle,
      isReload = false,
      isClearCheck = false,
      extra,
    } = action;
    const { getParams } = useParams();
    const tableDynamicDisabledAction = ['deletes', 'exports']; //表格默认动态禁用操作
    let { dynamicDisabled } = action;
    const extraData = { router, reload, action }; // handle传出数据
    if (tableDynamicDisabledAction.includes(name)) {
      dynamicDisabled = (data: any) => {
        return data.list.length === 0;
      };
    }
    if (dynamicDisabled) {
      if (isFunction(dynamicDisabled)) {
        action.dynamicDisabled = dynamicDisabled(data);
      }
    } else {
      action.dynamicDisabled = false;
    }

    if (state === 'edit') {
      action.finalHandle = () => {
        tableEdit(getKey(data));
      };
      return action;
    }

    if (state === 'save') {
      action.finalHandle = () => {
        console.log('save', getKey(data));

        validate(getKey(data))
          .then(() => {
            tableSave(getKey(data));
          })
          .catch((_: any) => {});
      };
      return action;
    }

    if (state === 'cancel') {
      action.finalHandle = () => {
        console.log('cancel', getKey(data));
        tableCancel(getKey(data));
      };
      return action;
    }

    if (state === 'delete') {
      action.finalHandle = () => {
        console.log("state === 'delete'", getKey(data));

        tableDelete(getKey(data));
      };
      return action;
    }

    if (state === 'add') {
      action.finalHandle = () => {
        addRow(data);
      };
      return action;
    }

    const handleList: Recordable = {
      confirm: null,
      checkApi: null,
      route: null,
      api: null,
      handle,
      isReload,
      isClearCheck,
    };
    let modelInstance: Recordable = {};
    if (name && name.toLowerCase().includes('exports')) {
      action.finalHandle = () => {
        xlsxExport({ data: data.list, ...extra } as any);
      };
      return action;
    }

    if (name && name.toLowerCase().includes('import')) {
      if (!action.handle) {
        action.finalHandle = () => {
          xlsxImport({ ...extra, reload } as any);
        };
        return action;
      }
    }

    function routeGo(toRoute: any) {
      const query = getParams(data, dynamicParams, defaultParams);

      if (isString(toRoute)) {
        router.push({ path: getPath(toRoute, data), query });
      } else {
        if (toRoute.path) {
          toRoute.path = getPath(toRoute.path, data);
          toRoute.query = query;
        }
        if (toRoute.name) {
          toRoute.query = query;
        }
        router.push(toRoute);
      }
    }

    if (checkApi) {
      handleList.checkApi = () => {
        const params = getParams(data, checkDynamicParams, checkDefaultParams);
        const requestConfig: AxiosRequestConfig = { method: 'get' };
        return httpRequest({ api: checkApi, params, pathParams: data, requestConfig });
      };
    }

    if (api) {
      handleList.api = () => {
        const params = getParams(data, dynamicParams, defaultParams);
        const requestConfig: AxiosRequestConfig = { method: 'post' };
        if (__APP_INFO__.serviceMode === 'saas') {
          if (requestConfig.headers) {
            requestConfig.headers.resourceCode = action.name;
          } else {
            requestConfig.headers = {
              resourceCode: action.name,
            };
          }
        }
        console.log('eeee', requestConfig);
        return httpRequest({ api, params, pathParams: data, requestConfig }).then(() => {
          showSuccess !== false && NsMessage.success(`${label}成功`);
        });
      };
    }

    //todo router name支持
    if (toRoute) {
      handleList.route = () => {
        return routeGo(toRoute);
      };
    }

    const modeUpdate = (prop: Recordable) => {
      if (!isEmpty(modelInstance)) {
        modelInstance.update(prop);
      }
    };
    action.finalHandle = async () => {
      modeUpdate({
        okButtonProps: {
          disabled: true,
        },
      });
      if (handleList.checkApi) await handleList.checkApi();
      if (handleList.route) return handleList.route();
      if (handleList.api) await handleList.api();
      // handleList.api && showSuccess !== false && NsMessage.success(`${label}成功`);
      try {
        if (handleList.handle) await handleList.handle(data, name, { ...extraData });
      } catch (error) {
        console.log(error);
      }
      if (isReload) {
        isFunction(reload) && reload();
      }
      if (isClearCheck) {
        isFunction(clearCheck) && clearCheck();
      }
      setTimeout(() => {
        modeUpdate({
          okButtonProps: {
            disabled: false,
          },
        });
      }, 100);
    };

    if (confirm) {
      const _finalHandle: any = action.finalHandle;
      const { title, content, icon, okText, okButtonProps } = confirm as Confirm;
      action.finalHandle = () => {
        modelInstance = NsModal.confirm({
          title: title || '警告',
          content: content || `确定要${label}吗？`,
          icon: icon || createVNode(ExclamationCircleOutlined),
          okText: okText || '确认',
          cancelText: '取消',
          okButtonProps,
          onOk: _finalHandle,
        });
      };
    }

    return action;
  }

  return {
    filterAction,
    filterActionNoAuth,
    transformAction,
  };
}
