import { importBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { ElLoading } from 'element-plus';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

const excelPattern = /\.(xls|xlsx)$/;

const isExcelResponse = res => {
  const contentType = res.headers['content-type'] || res.data.type || '';
  return contentType.includes('application/vnd.ms-excel');
};

const parseBlobJson = async blob => {
  const text = await blob.text();
  return text ? JSON.parse(text) : {};
};

/**
 * 加工后端返回的导入失败明细 Excel。
 * 若传入 failDetailDecorator（函数），则动态加载 exceljs 读取 blob 流，
 * 交由 decorator 完成改写原因列、调整列宽等加工，再导出新的 blob；
 * 否则原样返回 blob（保持旧行为，不影响未使用 decorator 的模块）。
 * @param {Blob} blob 后端返回的失败明细 Excel 流
 * @param {String} businessName 业务名称（如「货物类型」）
 * @param {Function} [failDetailDecorator] async (workbook, { businessName }) => void
 * @returns {Promise<Blob>}
 */
const decorateFailExcel = async (blob, businessName, failDetailDecorator) => {
  if (typeof failDetailDecorator !== 'function') return blob;
  const ExcelJS = await import('exceljs');
  const buf = await blob.arrayBuffer();
  const workbook = new ExcelJS.Workbook();
  await workbook.xlsx.load(buf);
  await failDetailDecorator(workbook, { businessName });
  const out = await workbook.xlsx.writeBuffer();
  return new Blob([out], { type: 'application/vnd.ms-excel' });
};

/**
 * 打开导入弹窗
 * @param {Object} vm 组件实例
 * @param {String} businessName 业务名称，用于失败明细文件命名
 * @param {Function} [onSuccess] 导入成功回调
 * @param {Object} [options] 扩展项
 * @param {Function} [options.failDetailDecorator] 失败明细加工函数，用于对后端返回的失败 Excel 标红/改写原因
 */
export const openImportDialog = (vm, businessName, onSuccess, options = {}) => {
  const { failDetailDecorator } = options;
  const excelOption = vm.excelOption || vm.excelOptionConfig;
  const column = vm.findColumn(excelOption?.column || [], 'excelFile');
  if (!column) {
    vm.$message.error('导入配置异常，请稍后重试');
    return;
  }
  column.httpRequest = (option, uploadColumn) =>
    handleImportExcel(vm, option, uploadColumn, businessName, onSuccess, { failDetailDecorator });
  vm.excelBox = true;
};

export const handleImportExcel = async (vm, option, column, businessName, onSuccess, options = {}) => {
  const { failDetailDecorator } = options;
  const file = option.file;
  const fileName = file && file.name ? file.name.toLowerCase() : '';
  if (!excelPattern.test(fileName)) {
    vm.$message.error('请上传 .xls,.xlsx 标准格式文件');
    if (typeof option.onError === 'function') {
      option.onError(new Error('请上传 .xls,.xlsx 标准格式文件'));
    }
    return;
  }

  NProgress.start();
  const loading = ElLoading.service({
    lock: true,
    text: '导入中',
    background: 'rgba(255, 255, 255, 0.7)',
  });
  try {
    const res = await importBlob(column.action, file);
    if (isExcelResponse(res)) {
      const decorated = await decorateFailExcel(res.data, businessName, failDetailDecorator);
      downloadXls(
        decorated,
        `${businessName}导入失败明细${vm.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`
      );
      vm.$message.warning('部分数据导入失败，已下载失败明细');
    } else {
      const result = await parseBlobJson(res.data);
      if (result.code !== 200) {
        vm.$message.error(result.msg || '导入失败');
        if (typeof option.onError === 'function') {
          option.onError(new Error(result.msg || '导入失败'));
        }
        return;
      }
      vm.$message.success('导入完成');
    }
    vm.excelBox = false;
    vm.excelForm = {};
    if (typeof onSuccess === 'function') {
      onSuccess();
    } else if (typeof vm.onLoad === 'function') {
      vm.onLoad(vm.page, vm.query);
    } else if (typeof vm.initTree === 'function') {
      vm.initTree();
    }
    if (typeof option.onSuccess === 'function') {
      option.onSuccess(res);
    }
  } catch (error) {
    vm.$message.error(error.message || '导入失败');
    if (typeof option.onError === 'function') {
      option.onError(error);
    }
  } finally {
    loading.close();
    NProgress.done();
  }
};
