import React from "react";
import { TableAddon, TableColumn } from "../TableProps";

export interface TableHeaderGroup {
  /**
   * 分组头标识
   */
  key: string;

  /**
   * 分组头内容
   */
  title?: React.ReactNode;

  /**
   * 对齐规则，左中右
   * @default "left"
   * @since 2.6.0
   */
  align?: TableColumn["align"];

  /**
   * 子分组或 Column
   */
  children?: string[];
}

export interface GroupableOptions {
  /**
   * 分组表头配置
   */
  headerGroups: TableHeaderGroup[];
}

export interface TableGroupableHeadItem extends TableHeaderGroup {
  order?: number;
  level?: number;
  colSpan?: number;
  rowSpan?: number;
  isLeaf?: boolean;
}

function getRows(groups: TableHeaderGroup[], columns: TableColumn[]) {
  const groupMap: Record<string, TableGroupableHeadItem> = {};
  const parentMap: Record<string, string> = {};
  const headIndexMap: Record<string, number> = {};
  groups.forEach(({ key, title, align, children }) => {
    groupMap[key] = { key, title, align, children };
    children.forEach(child => {
      parentMap[child] = key;
    });
  });
  columns.forEach(({ key }, index) => {
    headIndexMap[key] = index;
  });

  // 获取各分组 [层级，包含列数，排序]
  const traverse = (node: string): [number, number, number] => {
    if (groupMap[node] && groupMap[node].children) {
      let level = -1;
      let colSpan = 0;
      let minIndex = columns.length;
      groupMap[node].children.forEach(child => {
        const [childLevel, childColSpan, childIndex] = traverse(child);
        level = Math.max(childLevel, level);
        colSpan += childColSpan;
        minIndex = Math.min(minIndex, childIndex);
      });
      return [level + 1, colSpan, minIndex];
    }
    // 原始列
    return [0, 1, headIndexMap[node]];
  };

  const rows: TableGroupableHeadItem[][] = [];

  // 分组头
  groups.forEach(({ key }) => {
    const [level, colSpan, order] = traverse(key);
    groupMap[key] = {
      ...groupMap[key],
      order,
      level,
      colSpan,
    };
    if (!rows[level]) {
      rows[level] = [groupMap[key]];
    } else {
      rows[level].push(groupMap[key]);
    }
  });

  const headRowSpanMap: Record<string, number> = {};

  // 原始头
  columns.forEach(({ key }) => {
    const level = parentMap[key]
      ? groupMap[parentMap[key]].level - 1
      : (rows.length || 1) - 1;
    const head = {
      key,
      isLeaf: true,
      order: headIndexMap[key],
      rowSpan: level + 1,
    };
    if (!rows[level]) {
      rows[level] = [head];
    } else {
      rows[level].push(head);
    }
    headRowSpanMap[key] = head.rowSpan;
  });

  // 排序
  return [
    rows.map(row => row.sort((a, b) => a.order - b.order)).reverse(),
    headRowSpanMap,
  ];
}

export function groupable({ headerGroups }: GroupableOptions): TableAddon {
  let rows;
  let headRowSpanMap;
  return {
    getInfo: () => ({ name: "groupable" }),
    onInjectProps: props => {
      [rows, headRowSpanMap] = getRows(headerGroups, props.columns);
      return { ...props, headerRows: rows };
    },
    onInjectColumn: previous => (
      record,
      rowKey,
      recordIndex,
      column,
      columnIndex
    ) => {
      const { props, ...result } = previous(
        record,
        rowKey,
        recordIndex,
        column,
        columnIndex
      );

      if (recordIndex === -1) {
        return {
          ...result,
          props: {
            ...props,
            rowSpan: headRowSpanMap ? headRowSpanMap[column.key] : undefined,
          },
        };
      }

      return { ...result, props };
    },
  };
}
