/*
 * @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';
import React from 'react';
import { formatEnum, type EnumOptions } from './format';

export enum TableCellValueType {
  /** 序号 */
  Index = 'Index',
  /** 文本 */
  Text = 'Text',
  /** 日期 */
  Date = 'Date',
  /** 数组 */
  Array = 'Array',
  /** 链接 */
  Link = 'Link',
  /** 枚举 */
  Enum = 'Enum',
  /** 自定义 */
  Custom = 'Custom',
}

export type TableCellValueOptions<T> = {
  /** 页数，类型为 Index 时有效 */
  page?: number;
  /** 分页大小，类型为 Index 时有效 */
  pageSize?: number;
  /** 取数组对象的哪个属性值，类型为 Array 时有效 */
  property?: string;
  /** 日期格式，类型为 Date 时有效*/
  dateFormat?: string;
  /** 链接点击回调，类型为 Link 时有效 */
  onClick?: (record: T, e: React.MouseEvent) => void;
  /** 枚举选项，类型为 Enum 时有效*/
  options?: EnumOptions[];
  /** 自定义函数，类型为 Custom 时有效*/
  format?: (
    value: any | undefined | null,
    record?: T,
    index?: number,
  ) => React.ReactNode | undefined | null;
  /** 省略时是否可以复制 */
  copyable?: boolean;
};

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

/**
 * 日期转换函数
 * @param {string | undefined} dateFormat - 日期格式
 * @returns {TableCellFormatter} Table cell 渲染函数
 */
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(',');
  };
}

/**
 * Table cell render 函数
 * @param ellipsis - 是否省略
 * @param type - 类型
 * @param options - 选项
 * @returns Ant Design Table 的 render
 */
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.Enum:
        if (options?.options) {
          text = formatEnum(options.options)(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);
    } 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)}
        </Tooltip>
      );
    } else {
      return renderCell(type, text, false, record, options);
    }
  };
}

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

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

function renderText<T>(
  text: any | undefined | null,
  ellipsis: boolean | 'auto',
  options?: TableCellValueOptions<T>,
) {
  const { copyable } = options ?? {};
  if (ellipsis === 'auto') {
    return (
      <Typography.Paragraph
        style={{ marginBottom: 0 }}
        copyable={copyable}
        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;
