/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-param-reassign */
import { GridController } from '@ibiz-template/controller';
import {
  GridColumnModel,
  GridFieldColumnModel,
  GridGroupColumnModel,
  GridModel,
} from '@ibiz-template/model';
import { ControlVO } from '@ibiz-template/service';
import { useNamespace } from '@ibiz-template/vue-util';
import { clone } from 'ramda';
import { computed, CreateElement, ref } from 'vue';

export function generateColumnData(column: GridColumnModel, c: GridController) {
  const columnChildren: IData[] = [];
  if (column.source.columnType === 'GROUPGRIDCOLUMN') {
    // 如果是分组列，递归生成children
    (column as GridGroupColumnModel).children.forEach(child => {
      columnChildren.push(generateColumnData(child, c));
    });
  }
  const columnData = {
    title: column.title,
    width: column.source.widthUnit === 'STAR' ? undefined : column.width,
    minWidth: column.width,
    align: column.source.align?.toLowerCase() || 'center',
    slot: column.codeName,
    key: column.codeName,
    fieldName: (column as GridFieldColumnModel).deFieldName,
    ellipsis: true,
    tooltip: false, // todo 表格提示用title
    resizable: true,
    sortable: !c.noSort && column.source.enableSort ? 'custom' : false,
    columnType: column.source.columnType,
    userParams: column.source.userParams,
    className: column.source.getCellPSSysCss()?.cssName,
  };
  if (columnChildren.length > 0) {
    Object.assign(columnData, { children: columnChildren });
  }
  return columnData;
}

/**
 * 生成iViewTable要用的columns
 *
 * @author lxm
 * @date 2022-08-31 19:08:34
 * @export
 * @param {GridController} c
 * @returns {*}  {IData[]}
 */
export function generateIViewColumns(c: GridController): IData[] {
  const gridModel: GridModel = c.model;
  const columns: IData[] = [];
  // 生成所有表格列对应的iView表格需要的对象
  const tempColumns: IData[] = gridModel.columns.map(column => {
    return generateColumnData(column, c);
  });
  // 根据表格第一层的子去生成iView表格需要的columns
  gridModel.children.forEach((childColumn: GridColumnModel) => {
    const tempColumn = tempColumns.find(column => {
      return column.key === childColumn.codeName;
    });
    if (tempColumn) {
      columns.push(tempColumn);
    }
  });

  // 多选的时候给第一列添加选择列
  if (!c.singleSelect) {
    columns.splice(0, 0, { type: 'selection', width: 60 });
  }

  return columns;
}

/**
 * 获取iview的Table使用的columns响应式变量
 *
 * @author lxm
 * @date 2022-08-18 19:08:22
 * @export
 * @param {GridController} c
 * @returns [columns, originColumns 原始]
 */
export function useITableColumns(c: GridController) {
  // 原始iview用列数据
  const originColumns = ref<IData[]>([]);

  c.nerve.self.evt.on('created', () => {
    originColumns.value = generateIViewColumns(c);
  });

  //  获取可见列
  const getVisibleColumns = (columns: IData[]) => {
    return columns.filter((item: IData) => {
      if (c.hiddenColumnKeys.includes(item.key)) {
        return false;
      }
      if (item.columnType === 'GROUPGRIDCOLUMN') {
        if (item.children && item.children.length) {
          item.children = getVisibleColumns(item.children);
        } else {
          return false;
        }
      }
      return true;
    });
  };

  const renderHeader = (h: CreateElement, args: IData) => {
    const { column } = args;
    const { tooltip } = column.userParams || {};

    const ns = useNamespace('grid');
    const content = h(
      'i-tooltip',
      {
        props: {
          transfer: true,
          content: tooltip,
          transferClassName: ns.e('header-tooltip'),
        },
      },
      [h('i', { class: 'ivu-icon ivu-icon-ios-help-circle-outline' })],
    );
    return h('span', [column.title, content]);
  };

  const calcColumnTooltip = (column: IData) => {
    if (column.columnType === 'GROUPGRIDCOLUMN') {
      const children = column.children || [];
      children.forEach((child: IData) => {
        calcColumnTooltip(child);
      });
    } else {
      const { tooltip } = column.userParams || {};
      if (tooltip) {
        column.renderHeader = renderHeader;
      }
    }
  };

  // 实际iview使用的columns
  const columns = computed(() => {
    // 先浅拷贝
    let copy = clone(originColumns.value);
    copy = getVisibleColumns(copy);

    // 如果没有自适应列，深拷贝最后一个对象，改成自适应
    const flexColumn = copy.find(column => !column.width);
    const ctrlParams = c.model.source.getPSControlParam()?.ctrlParams;
    const isNotFlex = ctrlParams?.IS_NOT_FLEX === 'true';
    if (!flexColumn && !isNotFlex) {
      // 修改自适应列的索引，默认最后一个
      let index = copy.length - 1;
      if (copy[index].key === 'rowEdit') {
        index -= 1;
      }
      copy[index] = {
        ...copy[index],
        width: undefined,
      };
    }
    // 如果是操作列，固定右边
    const uaColumn = copy.find(column => column.columnType === 'UAGRIDCOLUMN');
    if (uaColumn) {
      const userParams = uaColumn.userParams;
      if (userParams && userParams.fixed === 'true') {
        uaColumn.fixed = 'right';
      }
    }
    // 计算列的固定状态
    const allNum = copy.length;
    let { frozenFirstColumn } = c.model;
    const { frozenLastColumn } = c.model;
    // 多选时固定列应添加选择列
    if (!c.singleSelect && frozenFirstColumn) {
      frozenFirstColumn += 1;
    }
    copy.forEach((column, index) => {
      if (frozenFirstColumn && index < frozenFirstColumn) {
        column.fixed = 'left';
      } else if (frozenLastColumn && index >= allNum - frozenLastColumn) {
        column.fixed = 'right';
      }
      if (
        (ibiz.env.enableGridRowBreak as any) === 'TRUE' ||
        ibiz.env.enableGridRowBreak === true
      ) {
        column.ellipsis = false;
      }
      if (c.controlParams.ENABLEGRIDROWBREAK) {
        column.ellipsis = c.controlParams.ENABLEGRIDROWBREAK !== 'TRUE';
      }
      calcColumnTooltip(column);
    });
    return copy;
  });
  return [columns, originColumns];
}

/**
 * 适配iview的table的事件
 *
 * @author lxm
 * @date 2022-09-05 21:09:42
 * @export
 * @param {GridController} c
 * @returns {*}
 */
export function useITableEvent(c: GridController) {
  const getOriginData = (data: IData): ControlVO => {
    return c.items.find(item => item.srfkey === data.srfkey)!;
  };

  function onRowClick(data: IData) {
    const origin = getOriginData(data);
    // 单选的时候选中效果靠这个回调
    if (c.singleSelect) {
      const selectedItem = c.selectedData.find(
        item => item.srfkey === data.srfkey,
      );
      c.onSelectionChange(selectedItem ? [] : [origin]);
    }
    c.onRowClick(origin);
  }

  function onDbRowClick(data: IData) {
    c.onDbRowClick(getOriginData(data));
  }

  function onSelectionChange(selection: IData[]) {
    // 单选的时候选中效果靠点击事件
    if (!c.singleSelect) {
      const origins: IData[] = [];
      selection.forEach(item => {
        const find = getOriginData(item);
        if (find) {
          origins.push(find);
        }
      });
      c.onSelectionChange(origins);
    }
  }

  function onSortChange(opts: {
    column: IData;
    key: string;
    order: 'asc' | 'desc' | 'normal';
  }) {
    const { column, order } = opts;
    const order1 = order === 'asc' || order === 'desc' ? order : undefined;
    c.setSort(column.fieldName, order1);
    c.load();
  }
  return { onRowClick, onDbRowClick, onSelectionChange, onSortChange };
}

/**
 * 使用表格分页组件
 *
 * @author lxm
 * @date 2022-09-06 17:09:09
 * @export
 * @param {GridController} c
 * @returns {*}
 */
export function useAppGridPagination(c: GridController) {
  function onPageChange(page: number) {
    if (!page || page === c.curPage) {
      return;
    }
    c.curPage = page;
    c.load();
  }

  function onPageSizeChange(size: number) {
    if (!size || size === c.size) {
      return;
    }
    c.size = size;

    // 当page为第一页的时候切换size不会触发pageChange，需要自己触发加载
    if (c.curPage === 1) {
      c.load();
    }
  }

  function onPageReset() {
    c.curPage = 1;
    c.load();
  }
  return { onPageChange, onPageSizeChange, onPageReset };
}

export function renderAttrs(model: GridModel, params: IParams): IParams {
  const attrs: IParams = {};
  model.controlAttributes?.forEach(item => {
    // 表格合并行列应该排除由表格内置合并单元格方法处理
    if (item.attrName !== 'span-method') {
      if (item.attrName && item.attrValue) {
        const args = {
          ...params,
        };
        const code = `return (function() { ${item.attrValue}} )();`;
        // eslint-disable-next-line no-new-func
        const fn = new Function(...Object.keys(args), code);
        const result = fn.apply({}, Object.values(args));
        return result;
      }
    }
  });
  return attrs;
}
