/*
 * @Author: 赵伟
 * @Date: 2024-06-26 10:05:52
 * @Description: Table Cell 自定义 render
 */

import { isEmpty } from '@/utils';
import { formatDate } from '@/utils/date';
import { Tooltip, TooltipProps, Typography } from 'antd';
import dayjs from 'dayjs';

export enum TableCellValueType {
  Index = 'Index',
  Text = 'Text',
  Date = 'Date',
  Array = 'Array',
  Link = 'Link',
  Custom = 'Custom',
}

export type TableCellValueOptions<T> = {
  page?: number; // 类型为 Index 时有效
  pageSize?: number; // 类型为 Index 时有效
  property?: string; // 类型为 Array 时有效
  dateFormat?: string; // 类型为 Date 时有效
  onClick?: (record: T, e: React.MouseEvent) => void; // 类型为 Link 时有效
  format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; // 类型为 Custom 时有效
};

type TableCellFormatter = (value: any | undefined | null) => string | undefined | null;

// 日期转换函数
function formatDateText(dateFormat?: string): TableCellFormatter {
  return (value: any | undefined | null): ReturnType<TableCellFormatter> => {
    if (value === undefined || value === null || value === '') {
      return null;
    }
    if (!dayjs(value).isValid()) {
      return null;
    }
    return formatDate(value, dateFormat);
  };
}

/**
 * 数组转换函数，将数组元素转换为字符串，用逗号分隔
 * @param {string} property 如果数组元素是对象，那么取数组元素的某个属性
 * @returns {TableCellFormatter} Table cell 渲染函数
 */
function formatArray(property?: string): TableCellFormatter {
  return (value: any | undefined | null): ReturnType<TableCellFormatter> => {
    if (
      value === undefined ||
      value === null ||
      Array.isArray(value) === false ||
      value.length === 0
    ) {
      return null;
    }

    const list =
      property && typeof value[0] === 'object' ? value.map((item) => item[property]) : value;
    return list.join(',');
  };
}

function tableCellRender<T>(
  ellipsis: boolean | TooltipProps | 'auto' = false,
  type: TableCellValueType = TableCellValueType.Text,
  options?: TableCellValueOptions<T>,
) {
  return (value: any | undefined | null, record: T, index: number) => {
    let text = value;
    switch (type) {
      case TableCellValueType.Index:
        text = (options?.page ?? 0) * (options?.pageSize ?? 0) + index + 1;
        break;
      case TableCellValueType.Text:
      case TableCellValueType.Link:
        text = value;
        break;
      case TableCellValueType.Date:
        text = formatDateText(options?.dateFormat)(value);
        break;
      case TableCellValueType.Array:
        text = formatArray(options?.property)(value);
        break;
      case TableCellValueType.Custom:
        text = options?.format?.(value, record, index);
        break;
      default:
        break;
    }

    if (ellipsis === 'auto' && text) {
      return renderCell(type, text, 'auto', record, options?.onClick);
    } else if (ellipsis && text) {
      const tooltipProps = typeof ellipsis === 'object' ? ellipsis : {};
      const { overlayStyle, ...rest } = tooltipProps;
      return (
        <Tooltip {...rest} overlayStyle={{ maxWidth: 400, ...overlayStyle }} title={text}>
          {renderCell(type, text, true, record, options?.onClick)}
        </Tooltip>
      );
    } else {
      return renderCell(type, text, false, record, options?.onClick);
    }
  };
}

function renderCell<T>(
  type: TableCellValueType,
  text: any | undefined | null,
  ellipsis: boolean | 'auto',
  record: T,
  onClick?: (record: T, e: React.MouseEvent) => void,
) {
  return type === TableCellValueType.Link
    ? renderLink(text, ellipsis, record, onClick)
    : renderText(text, ellipsis);
}

function renderLink<T>(
  text: any | undefined | null,
  ellipsis: boolean | 'auto',
  record: T,
  onClick?: (record: T, e: React.MouseEvent) => void,
) {
  return (
    <a className="kf-table-row-link" onClick={(e) => onClick?.(record, e)}>
      {renderText(text, ellipsis)}
    </a>
  );
}

function renderText(text: any | undefined | null, ellipsis: boolean | 'auto') {
  if (ellipsis === 'auto') {
    return (
      <Typography.Paragraph
        style={{ marginBottom: 0 }}
        ellipsis={{
          tooltip: {
            title: text,
            destroyTooltipOnHide: true,
            overlayStyle: { maxWidth: 400 },
          },
        }}
      >
        {!isEmpty(text) ? text : '--'}
      </Typography.Paragraph>
    );
  }

  return (
    <span
      style={
        ellipsis
          ? {
              whiteSpace: 'nowrap',
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              wordBreak: 'break-all',
              display: 'inline-block',
              maxWidth: '100%',
              verticalAlign: 'middle',
            }
          : undefined
      }
    >
      {!isEmpty(text) ? text : '--'}
    </span>
  );
}

export default tableCellRender;
