import { useState } from 'react';
import { Modal } from 'antd';
import { giveFilePostDataInfoForTrue } from '@/webPublic/one_stop_public/Base16';
import { queryOauthActionPath } from '@/webPublic/one_stop_public/utils/queryConfig';
import { getToken } from '@/webPublic/one_stop_public/utils/token';
import { deepCopy } from '@/webPublic/zyd_public/utils/utils';
import { getTransformApi } from '@/webPublic/one_stop_public/2022beidianke/localstorageTransform';
import moment from 'moment';

const apiUrl = queryOauthActionPath();

/**
 * 公共函数代码
 *
 * */

/**
 * 列表获取纵向合并数据
 * mergeKey : 需要合并的表头key
 * data : 列表数据
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 * 返回值
 * rowSpanData 列合并数据，colSpanData行合并数据
 * */
export function getSpanJson({
  mergeKey,
  data,
  eliminateRow = [],
  eliminateCol = []
}) {

  const dataList = deepCopy(data);
  let rowSpanData ,colSpanData = null;
  try {
    rowSpanData = getRowSpanJson(mergeKey, dataList, eliminateRow);
  } catch (err) {
    console.table("rowSpanData",err);
  }
  try {
    colSpanData = getColSpanJson(mergeKey, dataList, eliminateCol);
  } catch (err) {
    console.table("colSpanData",err);
  }
  return {
    rowSpanData,
    colSpanData,
  };
}

function getRowSpanJson(cloumnNames, data, eliminateStr = []) {
  data = deepCopy(data);
  //纵向合并
  // 获取列的 dataIndex 集合
  var rowSpanJson = {};
  //保存上一个name
  var beforeNameMap = {};
  //相同name出现的次数
  var countMap = {};
  //该name第一次出现的位置
  var startIndexMap = {};
  for (var idx = 0; idx < data.length; idx++) {
    var dataItem = data[idx];
    for (var idj = 0; idj < cloumnNames.length; idj++) {
      var keyItem = cloumnNames[idj];
      var dataItemValue = dataItem[keyItem];
      if (idx === 0) {
        beforeNameMap[keyItem] = dataItem[keyItem];
        countMap[keyItem] = 1;
        startIndexMap[keyItem] = 0;
        rowSpanJson[keyItem] = new Array(data.length);
        rowSpanJson[keyItem][0] = 1;
        continue;
      }
      if (dataItemValue === beforeNameMap[keyItem] && eliminateStr.indexOf(dataItemValue) === -1) {
        countMap[keyItem] = countMap[keyItem] + 1;
        rowSpanJson[keyItem][startIndexMap[keyItem]] = countMap[keyItem];
        rowSpanJson[keyItem][idx] = 0;
      } else {
        countMap[keyItem] = 1;
        beforeNameMap[keyItem] = dataItemValue;
        startIndexMap[keyItem] = idx;

        rowSpanJson[keyItem][idx] = 1;
      }
    }
  }
  return rowSpanJson;
}

function getColSpanJson(cloumnNames, data, eliminateStr = []) {
  data = deepCopy(data);
  //横向合并
  var colSpanJson = {};
  for (let idx = 0; idx < data.length; idx++) {
    let dataItem = data[idx];
    let colSum = 1; //宽度
    let triggerColIndex = null; //记录触发时得位置
    let triggerColSum = 1; //记录触发时得位置
    let isCol = false;
    for (let idj = 0; idj < cloumnNames.length; idj++) {
      let keyItem = cloumnNames[idj];
      let dataItemValue = dataItem[keyItem];
      let dataItemValueNext = idj < cloumnNames.length - 1 ? dataItem[cloumnNames[idj + 1]] : null;
      //console.log("dataItemValue",dataItemValue,idj)
      if (idx === 0) {
        colSpanJson[keyItem] = new Array(data.length);
      }
      if (
        !isCol &&
        dataItemValue === dataItemValueNext &&
        eliminateStr.indexOf(dataItemValue) === -1
      ) {
        //触发合并
        triggerColIndex = keyItem;
        isCol = true;
      }
      if (isCol && (dataItemValue !== dataItemValueNext || dataItemValueNext == null)) {
        //合并结束
        isCol = false;
      }
      if (isCol) {
        //计数
        triggerColSum++;
      }
      if (!isCol && triggerColIndex !== null) {
        colSpanJson[triggerColIndex][idx] = triggerColSum;
        colSpanJson[keyItem][idx] = 0;
        triggerColIndex = null;
      } else if (isCol && triggerColIndex !== null) {
        colSpanJson[keyItem][idx] = 0;
      } else {
        colSpanJson[keyItem][idx] = colSum;
      }
    }
  }
  //console.log("colSpanJson",colSpanJson)
  return colSpanJson;
}

/**
 * ant表头转换成二维数组对象。
 * columns : ant的表头
 *
 * 返回值
 * columnsList 基础数据
 * columnsMerges 合并数据
 * columnsKey key对应的列
 * columnsHeight 行数
 * */
export function getColumns(columns) {
  columns = deepCopy(columns);

  const uj = {
    t: 1,
    v: '序号',
    s: 'header',
  };
  let columnsHeight = getColumnsMaxLevel(columns); //递归行数
  let columnsKey = [];
  const columnsList = new Array(columnsHeight).fill([]);
  let col = 1;
  for (var i in columnsList) {
    columnsList[i] = new Array(getColumnsWidth(columns)).fill({});
  }

  function getColumnsData(data = [], res = [], level = 1) {
    try {
      for (let item of data) {
        //item.key = i;
        let isLast = !item.children;
        item.level = level;
        item.isLast = isLast;
        item.width = !isLast ? getColumnsWidth(item.children) : 1;
        item.col = col;
        res.push(item);
        columnsList[level - 1][col - 1] = {
          ...uj,
          v: item.title,
        };
        if (!isLast) {
          if (Array.isArray(item.children)) {
            let x = level + 1;
            getColumnsData(item.children, res, x);
          }
        } else {
          col++;
          columnsKey.push(item['dataIndex']);
        }
      }
      return res;
    } catch (e) {
      console.table("getColumnsData",e);
      return false;
    }
  }

  //递归行数
	function getColumnsMaxLevel(arr = [] ) { 
		//递归计算树形数据最大的层级数
		let maxLevel = 0;
		(function multiArr(arr, level=0) {
			++level;
			maxLevel = Math.max(level, maxLevel);
			for (let i = 0; i < arr.length; i++) {
				let item = arr[i];
				item.level = level;
				if (item.children && item.children.length > 0) {
					multiArr(item.children, level);
				} else {
					delete item.children;
				}
			}
		})(arr, 0);
		return maxLevel;
  } 


  //递归当前数据宽度
  function getColumnsWidth(data = [], sum = 0) {
    for (let item of data) {
      if (!item.children) {
        sum++;
      } else {
        sum = getColumnsWidth(item.children, sum);
      }
    }
    return sum;
  }

  let columnsHandle = getColumnsData(columns)
    .filter((v, i) => {
      return (v.level < columnsHeight && v.isLast) || v.width > 1;
    });
  let columnsMerges = [];
  columnsHandle.forEach((v, i) => {
    let {
      isLast,
      width,
      col,
      level
    } = v;
    let nowCol = col - 1;
    let nowLevel = level - 1;
    if (isLast && width === 1) {
      //合并表格的 开始行、结束行、开始列、结束列
      columnsMerges.push([nowLevel, columnsHeight - 1, nowCol, nowCol]);
    }
    if (!isLast && width > 1) {
      columnsMerges.push([nowLevel, nowLevel, nowCol, nowCol + width - 1]);
    }
  });
  return {
    columnsList,
    columnsMerges,
    columnsKey,
    columnsHeight,
  };
}

/**
 *
 * @param {sqlKey,columns,styles,fileName,ext,allValues} param
 * 表头和sql数据导出（表头合并表格，数据不合并表格）
 * sqlKey : 数据sql编码
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 */
export function getColumnsSqlKeyRealize({
  sqlKey,
  columns,
  styles,
  fileName = '导出文件',
  ext = 'xlsx',
  allValues = JSON.stringify({})
}) {
  columns = deepCopy(columns);

  let {
    columnsList,
    columnsMerges,
    columnsKey
  } = getColumns(columns);

  let content = {
    sheets: [
      {
        name: fileName,
        cells: columnsList,
        merges: columnsMerges,
        sqlKey: sqlKey, //sql编码
        sqlKeyHeader: columnsKey, //sql对应key对应列
      },
    ],
    styles: {
      header: {
        font: {
          bold: false,
          fontHeightInPoints: 12,
        },
        alignment: 'CENTER',
        borderLeft: 'THIN',
        borderTop: 'THIN',
        borderBottom: 'THIN',
        borderRight: 'THIN',
        verticalAlignment: 'CENTER', //TOP、CENTER、BOTTOM、JUSTIFY、DISTRIBUTED
        wrapText: true,
        rowHeights: 20,
        colWidths: 250,
      },
      head: {
        font: {
          bold: true,
        },
        alignment: 'CENTER',
      },
    },
  };
  if (styles) {
    content.styles = styles;
  }
  try {
    let getFileData = giveFilePostDataInfoForTrue(
      {
        content: JSON.stringify(content),
        title: fileName,
        allValues: allValues
      },
      `${apiUrl + '/DataObjApi/exportCustom'}`,
    );
    let token = getToken();
    downloadFile(
      getFileData.url,
      {
        ...getFileData.datas,
        token: token,
      },
      fileName,
      ext,
    );
  } catch (err) {
    console.table("getColumnsSqlKeyRealize",err);
  }
}

/**
 *
 * @param {data,columns,styles,defect,fileName,ext,url,eliminateRow,eliminateCol} param
 * 表头和数据导出（合并表格）
 * data : ant基础数据
 * columns : ant表头基础数据
 * styles : 导出excl样式
 * defect : 为null时默认数据
 * fileName : 导出文件名
 * ext : 导出后缀 目前xecl、dbf
 * url : 接口地址
 * eliminateRow : 列需要忽略合并的数据
 * eliminateCol : 行需要忽略合并的数据
 *
 */
export function getColumnsDataRealize({
  data = [],
  mergeKey = [],
  columns,
  styles,
  defect = null,
  fileName = '导出文件',
  ext = 'xlsx',
  eliminateRow = [],
  eliminateCol = [],
}) {
  columns = deepCopy(columns);
  data = deepCopy(data);
  let {
    columnsList,
    columnsMerges,
    columnsKey,
    columnsHeight
  } = getColumns(columns);
  let {
    colSpanData,
    rowSpanData
  } = getSpanJson({
    mergeKey,
    data,
    eliminateRow,
    eliminateCol
  });
  // 处理数据
  let bodyData = [];
  let dataMerges = [];
  const uj = {
    t: 1,
    v: '序号',
    s: 'header',
  };
  try {
    data.forEach((dv, di) => {
      let nowArroy = new Array(columnsKey.length).fill({});
      columnsKey.forEach((av, ai) => {
        nowArroy[ai] = {
          ...uj,
          v: av in dv && dv[av] != null ? dv[av].toString() : defect || '',
        };
      });
      bodyData.push(nowArroy);
    });
    // 处理合并数据
    mergeKey.forEach((mv, mi) => {
      rowSpanData[mv].forEach((cv, ci) => {
        if (cv > 1) {
          //合并表格的 开始行、结束行、开始列、结束列
          let rowIndex = columnsKey.indexOf(mv);
          dataMerges.push([columnsHeight + ci, columnsHeight + ci + cv - 1, rowIndex, rowIndex]);
        }
      });
      colSpanData[mv].forEach((cv, ci) => {
        if (cv > 1) {
          //合并表格的 开始行、结束行、开始列、结束列
          let rowIndex = columnsKey.indexOf(mv);
          dataMerges.push([columnsHeight + ci, columnsHeight + ci, rowIndex, rowIndex + cv - 1]);
        }
      });
    });
  } catch (err) {
    console.table("getColumnsDataRealize",err);
  }


  let content = {
    sheets: [
      {
        name: fileName,
        cells: [...columnsList, ...bodyData],
        merges: [...columnsMerges, ...dataMerges],
      },
    ],
    styles: {
      header: {
        font: {
          bold: false,
          fontHeightInPoints: 12,
        },
        alignment: 'CENTER',
        borderLeft: 'THIN',
        borderTop: 'THIN',
        borderBottom: 'THIN',
        borderRight: 'THIN',
        verticalAlignment: 'CENTER', //TOP、CENTER、BOTTOM、JUSTIFY、DISTRIBUTED
        wrapText: true,
        rowHeights: 20,
        colWidths: 250,
      },
      head: {
        font: {
          bold: true,
        },
        alignment: 'CENTER',
      },
    },
  };
  if (styles) {
    content.styles = styles;
  }
  try {
    let getFileData = giveFilePostDataInfoForTrue(
      {
        content: JSON.stringify(content),
        title: fileName,
      },
      `${apiUrl + '/DataObjApi/exportCustom'}`,
    );
    let token = getToken();
    downloadFile(
      getFileData.url,
      {
        ...getFileData.datas,
        token: token,
      },
      fileName,
      ext,
    );
  } catch (err) {
    console.table("getColumnsDataRealize",err);
  }

}

// ant列表组件合并表格 render属性，合并纵向、横向。
export function renderContentAll(value, row, index, key, spanData, cloumnNames = []) {
  let colSpan,
    rowSpan = null;
  try {
    colSpan = spanData.colSpanData[key][index];// 横向合并
    rowSpan = spanData.rowSpanData[key][index];// 纵向合并
  } catch (err) {
    console.table("renderContentAll",err);
  }
  const obj = {
    children: value,
    props: {
      rowSpan: rowSpan,
      colSpan: colSpan
    }
  };
  return obj;
}

// ant列表组件合并表格 render属性，合并纵向。 meanwhileKey :key 是本身字段key，value 是同步的字段key
export function renderContentRow(value, row, index, key, spanData, cloumnNames = [], meanwhileKey = {}) {
  let colSpan,
    rowSpan = null;
  try {
    if (cloumnNames.indexOf(key) !== -1) {
      rowSpan = spanData.rowSpanData[key][index];// 纵向合并
    } else {
      if (key in meanwhileKey && meanwhileKey[key]) {
        let meanwhileKeyValue = meanwhileKey[key];
        rowSpan = spanData.rowSpanData[meanwhileKeyValue][index];// 同步字段 的纵向合并
      } else {
        rowSpan = 1;
      }
    }
  } catch (err) {
    console.table("renderContentRow",err);
  }
  const obj = {
    children: value,
    props: {
      rowSpan: rowSpan,
      colSpan: 1
    }
  };
  return obj;
}


/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */
export function getWord({
  templatePath,
  params,
  title,
  allValues = {},
  listConfig = {},
  ext = 'docx',
}) {
  try {
    let getFileData = giveFilePostDataInfoForTrue(
      {
        templatePath: templatePath,
        params: JSON.stringify({
          ...listConfig,
          ...setObjectKey(params),
        }),
        title: `${title}.${ext}`,
        allValues: JSON.stringify({ ...allValues }),
      },
      apiUrl + `/DataColumnApi/exportWord`,
    );
    let token = getToken();
    downloadFile(
      getFileData.url,
      {
        ...getFileData.datas,
        token: token,
      },
      title,
      ext,
    );
  } catch (err) {
    console.table(err);
  }

}


/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */
export function getFileAndShow({
  templatePath,
  params,
  title,
  allValues = {},
  listConfig = {},
  ext = 'docx',
}) {
  try {
    let getFileData = giveFilePostDataInfoForTrue(
      {
        templatePath: templatePath,
        params: JSON.stringify({
          ...listConfig,
          ...setObjectKey(params),
        }),
        title: `${title}.${ext}`,
        allValues: JSON.stringify({ ...allValues }),
      },
      apiUrl + `/DataColumnApi/exportWord`,
    );
    let token = getToken();
    downloadFileAndShowModal(
      getFileData.url,
      {
        ...getFileData.datas,
        token: token,
      },
      title,
      ext,
    );
  } catch (err) {
    console.table(err);
  }

}


/**
 * 表头和数据导出（合并表格）
 * templatePath : word文档模板地址
 * params : word文档的替换参数
 * title : 导出文件名
 * allValues : sql参数
 * listConfig : 导出列表配置
 * ext : 导出后缀 目前xecl、dbf,docx,pdf
 * 返回值
 * */

export function getListWord({
  templatePath,
  paramsList = [],
  title,
  sonTitleKey,
  allValuesKey = [],
  listConfig = {},
  ext = 'zip',
  sonExt = 'pdf',
  files = []
}) {
  try {
    let content = [];
    paramsList.forEach((v, i) => {
      content.push({
        params: {
          ...setObjectKey(v),
          ...listConfig,
        },
        allValues: {
          ...getObjectsKey(allValuesKey, v)
        },
        title: (v[sonTitleKey] || "未设置名称") + `.${sonExt}`,
        files:JSON.stringify(files)
      });
    });

    let getFileData = giveFilePostDataInfoForTrue(
      {
        templatePath: templatePath,
        content: JSON.stringify(content),
        zipTitle: `${title}.${ext}`,
      },
      apiUrl + `/DataColumnApi/batchExportWord`,
    );

    let token = getToken();
    downloadFile(
      getFileData.url,
      {
        ...getFileData.datas,
        token: token,
      },
      title,
      ext,
    );
  } catch (err) {
    console.table(err);
  }
  function getObjectsKey(listKey = [], params = {}) {
    return (
      listKey
        .filter((key) => Object.keys(params).indexOf(key))
        .reduce(
          (acc, key) => ({
            ...acc,
            [key]: params[key] === null ? '' : params[key],
          }),
          {},
        )
    )
  }
}

function setObjectKey(data) {
  return (
    Object.keys(data)
      .reduce(
        (acc, key) => ({
          ...acc,
          ['${' + key + '}']: data[key] === null ? '' : data[key],
        }),
        {},
      )
  );
}

/**
 * 修改对象key
 * 支持对象、数组对象
 * @param {*} obj 数组对象或者对象
 * @param {*} setKey {"被修改的key":"修改后的key"}
 * @returns 
 */
export function upObjKey(obj, setKey = {},defaultValue="") {
  try {
    obj = deepCopy(obj);
    let objType = Object.prototype.toString.call(obj);
    if (obj && (objType.indexOf("Array") > -1 || objType.indexOf("Object") > -1) && Object.keys(setKey).length > 0) {
        if (objType === "[object Object]" && Object.keys(obj).length > 0) {
            for (var e in setKey) {
                let upKey = setKey[e];
                let { newKey = e, type, timeFormat } = getSetKeyValue(upKey); 
                obj = getSetKeyJson({
                    obj, e, newKey, type, timeFormat,defaultValue
                });
            }
        }
        if (objType === "[object Array]" && obj.length > 0) {
            obj.forEach((v, i, arr) => {
                for (var e in setKey) {
                    let upKey = setKey[e];
                    let { newKey  = e, type, timeFormat } = getSetKeyValue(upKey);
                    arr[i] = getSetKeyJson({
                        obj: v, e, newKey, type, timeFormat,defaultValue
                    });
                }
            })
        }
        return obj;
    } else {
        return null;
    }
  } catch (error) {
    console.log("upObjKey",error);
    return undefined;
  }
}
 
function getSetKeyValue(value) {
  let valeuType = Object.prototype.toString.call(value);
  let newName = null;
  let extendJson = {
      "type": "string"
  };
  if (valeuType === "[object String]") {
      newName = value;
  }
  if (valeuType === "[object Object]") {
      newName = value["new"];
      delete value["new"];
      extendJson = {
          ...extendJson,
          ...value
      };
  }
  return {
      newKey: newName,
      ...extendJson
  }
}
function getSetKeyJson({
  obj, e, newKey, type, timeFormat,defaultValue
}) {
  obj = deepCopy(obj);
  let value = obj[e];
  delete obj[e];
  switch (type) {
      case "time":
          obj[newKey] = (timeFormat && value ? moment(value).format(timeFormat) : value) || defaultValue;
          break;
      default:
          obj[newKey] = value || defaultValue;
  }
  return obj;
}


// 下载附件FormdataWrapper
function isObject(value) {
  return value === Object(value);
}

function isArray(value) {
  return Array.isArray(value);
}

function isFile(value) {
  return value instanceof File;
}

function makeArrayKey(key) {
  return key;
}

function FormdataWrapper(obj, fd, pre) {
  fd = fd || new FormData();
  Object.keys(obj)
    .forEach(function (prop) {
      var key = pre ? pre + '[' + prop + ']' : prop;
      if (isObject(obj[prop]) && !isArray(obj[prop]) && !isFile(obj[prop])) {
        FormdataWrapper(obj[prop], fd, key);
      } else if (isArray(obj[prop])) {
        obj[prop].forEach(function (value) {
          var arrayKey = makeArrayKey(key);
          if (isObject(value) && !isFile(value)) {
            FormdataWrapper(value, fd, arrayKey);
          } else {
            fd.append(arrayKey, value);
          }
        });
      } else {
        if (obj[prop] != null) fd.append(key, obj[prop]);
      }
    });
  return fd;
}

export async function downloadFile(url, params, fileName = '导出文件', ext = 'xlsx') {
  // console.log("downloadFile",url);
  const { transformApi, headersApi } = await getTransformApi(url);
  let headers = {
    Authorization: `bearer ${localStorage.getItem('antd-pro-token-onestop')}`,
  };
  // if(headersApi){
  //   headers.apis = headersApi;
  // }
  fetch(transformApi, {
    method: 'POST',
    body: FormdataWrapper(params),
    headers,
  })
    .then((res) => {
      if (res.status + '' !== '200') {
        return res.json();
      } else {
        return res.blob();
      }
    })
    .then((data) => {
      if (data instanceof Blob) {
        let a = document.createElement('a');
        let url = window.URL.createObjectURL(data);
        let filename = fileName + '.' + ext;
        a.href = url;
        a.download = filename;
        a.target = '_blank';
        a.click();
        window.URL.revokeObjectURL(url);
        a = null;
      } else {
      }
    })
    .catch((err) => {
      console.log(err);
    })
    .finally(() => {
      return true;
    });
}


export async function downloadFileAndShowModal(url, params, fileName = '导出文件', ext = 'xlsx') {
  // console.log("downloadFile",url);
  const { transformApi, headersApi } = await getTransformApi(url);
  let headers = {
    Authorization: `bearer ${localStorage.getItem('antd-pro-token-onestop')}`,
  };
  // if(headersApi){
  //   headers.apis = headersApi;
  // }
  fetch(transformApi, {
    method: 'POST',
    body: FormdataWrapper(params),
    headers,
  })
    .then((res) => {
      if (res.status + '' !== '200') {
        return res.json();
      } else {
        return res.blob();
      }
    })
    .then((data) => {
      if (data instanceof Blob) {
        let url = window.URL.createObjectURL(data);
        let filename = fileName + '.' + ext;
        /**
         * 微软word 文档在线预览
         https://view.officeapps.live.com/op/view.aspx?src=
         https%3A%2F%2Fwww.longchang.gov.cn%2Flcs%2Fgsgg%2F202207%2F3ae45ccac65d40d885f40ec385ae287a%2Ffiles%2F%25E9%259A%2586%25E6%2598%258C%25E5%25B8%2582%25E7%25AC%25AC%25E5%2585%25AB%25E4%25B8%25AD%25E5%25AD%25A6%25E5%258E%2595%25E6%2589%2580%25E6%2594%25B9%25E9%2580%25A0%25E9%25A1%25B9%25E7%259B%25AE%25E5%2585%25AC%25E5%2591%258A.doc&wdOrigin=BROWSELINK
         * */
        Modal.info({
          title: filename,
          width: 1000,
          content: <div>
            <embed width='100%'
              height='568px'
              name='plugin'
              id='pdfView'
              src={url}
              type='application/pdf'

              internalinstanceid='3'
              title={filename} />
          </div>,
          okText: '确定',
          onCancel: () => {
            window.URL.revokeObjectURL(url);
          },
          onOk: () => {
            window.URL.revokeObjectURL(url);
          },
        });
      } else {
      }
    })
    .catch((err) => {
      console.log(err);
    })
    .finally(() => {
      return true;
    });
}
