import React, {
  forwardRef,
  useCallback,
  useEffect,
  useImperativeHandle,
  useMemo,
  useState
} from 'react'
import styles from './index.module.scss'
import { DatePicker, Form, FormInstance, Input, Table, TableProps } from 'antd'
import ImageLazy from '../ImageLazy'
import classNames from 'classnames'
import dayjs from 'dayjs'
import { resJiLianFu, resTagFu } from '@/utils/dataChange'

interface MyTableProps extends Omit<TableProps, 'onChange'> {
  yHeight?: number //设置表格的高度
  list: any //表格数据
  columnsTemp: any[][] //表格展示
  total?: number //总数
  pageNum?: number
  pageSize?: number
  pagingInfo?: any | boolean
  onChange?: (pageNum: number, pageSize: number) => void
  lastBtn?: any //后面的操作按钮
  startBtn?: any
  classKey?: string //一个组件多次使用的时候要传递，分别设置style
  // 表格简单的合并
  merge?: { type: string; num: number; loc: 'rowSpan' | 'colSpan' }
  // 定制化表头
  myTitle?: { name: string; Com: React.ReactNode }
  // 为空的定制字段
  isNull?: string
  // 设置宽度
  widthSet?: any
  rowKey?: string
  readOnly?: boolean
  // 没有数据的时候展示
  emptyText?: boolean
}

export interface MyTableMethods {
  form: FormInstance<any>
}

export const getDesensitizeTxt = (txt: string, frontLen = 3, endLen = 4) => {
  if (!txt) return txt
  const totalVisible = frontLen + endLen
  if (txt.length <= totalVisible) {
    return txt
  }
  const frontStr = txt.substring(0, frontLen)
  const endStr = endLen > 0 ? txt.substring(txt.length - endLen) : ''
  const maskStr = '*'.repeat(txt.length - frontLen - endLen)

  return frontStr + maskStr + endStr
}

const MyTable = forwardRef<MyTableMethods, MyTableProps>(
  (
    {
      yHeight,
      list,
      columnsTemp,
      total,
      pageNum = 1,
      pageSize = 10,
      pagingInfo = {
        showQuickJumper: true,
        position: ['bottomCenter'],
        showSizeChanger: true
      },
      onChange,
      lastBtn = [],
      startBtn = [],
      classKey = '',
      merge,
      myTitle,
      isNull = '（空）',
      widthSet,
      rowKey = 'id',
      readOnly,
      emptyText,
      ...rest
    },
    ref
  ) => {
    // 点击操作高亮
    const [clickAc, setClickAc] = useState(0)
    const [form] = Form.useForm()

    // 表格内容定制化
    const tableComObj = useCallback(
      (key: string, val: string[], id?: any, backFu?: (id: number) => void) => {
        const obj = {
          // 超链接打开
          A: (
            <a href={val[1]} target='_blank' title={val[1]} rel='noreferrer'>
              {val[0]}
            </a>
          ),
          // 点击触发事件
          S: (
            <span
              className={classNames('MTclick', clickAc === id ? 'MTclickAc' : '')}
              onClick={() => {
                if (id && backFu) {
                  backFu(id)
                  setClickAc(id)
                }
              }}
            >
              {val[1]}
            </span>
          )
        }
        return Reflect.get(obj, key)
      },
      [clickAc]
    )

    useEffect(() => {
      const dom = document.querySelector(`.MyTable${classKey} .ant-table-body`) as HTMLDivElement

      if (dom && yHeight) dom.style.height = yHeight + 'px'
    }, [classKey, yHeight])

    // 页码变化
    const paginationChange = useCallback(
      () => (pageNum: number, pageSize: number) => {
        if (onChange) {
          onChange(pageNum, pageSize)
        }
      },
      [onChange]
    )

    const dataChangeFu = useCallback(
      (v: any) => {
        /**
         * index:序号
         * txt:正常数据
         * img:图片
         * txtChange:判断显示不同字段
         * text:文字比较多的情况
         */
        const obj = {
          index: (_: any, __: any, index: number) => index + 1 + (pageNum - 1) * pageSize,
          txt: (item: any) =>
            v[3] && !item[v[2]] ? (
              <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
            ) : item[v[2]] && item[v[2]] !== '0' ? (
              item[v[2]]
            ) : (
              isNull
            ),
          txtArr: (item: any) => (
            <div dangerouslySetInnerHTML={{ __html: (item[v[2]] || []).join('<br/>') }}></div>
          ),
          // 日期去掉00：00：00
          dateRes: (item: any) => {
            let res = item[v[2]] ? dayjs(item[v[2]]).format('YYYY-MM-DD') : isNull
            return res
          },
          // 多个字段拼接
          ping: (item: any) => (item[v[2]] || '') + (resJiLianFu(item[v[3]]) || '') || isNull,
          // 这个模块特有的级联控制
          txtC: (item: any) =>
            v[1] === '年代' && item[v[2]] === '其他' ? '其他' : resJiLianFu(item[v[2]]),
          txtCTag: (item: any) => {
            // resJiLianFu(item[v[2]], 'tag'),
            let resTxt = item[v[2]] || isNull
            if (resTxt) {
              return resTagFu(resTxt, v[3] || '藏品') || isNull
            }
            return resTxt || isNull
          },
          img: (item: any) =>
            v[3] && !item[v[2]] ? (
              <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
            ) : (
              <div className='tableImgAuto'>
                <ImageLazy
                  width={60}
                  height={60}
                  srcBig={item.thumbPc || item.filePath}
                  src={item[v[2]] || item.thumb}
                  offline={(item[v[2]] || item.thumb).includes('http')}
                />
              </div>
            ),
          // 附件大小
          fileSize: (item: any) => {
            if (item[v[2]]) {
              const resTxt = (item[v[2]] / 1024).toFixed(2)
              if (resTxt === '0.00') return '0.01'
              else return resTxt
            } else return isNull
          },
          txtChange: (item: any) => Reflect.get(v[3], item[v[2]]) || v[4] || isNull,
          text: (item: any) => {
            let tempCom: any = item[v[2]] || isNull

            if (tempCom.length >= v[3]) {
              tempCom = tempCom.substring(0, v[3]) + '...'
            }

            if (v[4]) {
              tempCom = tableComObj(v[4], [tempCom, item[v[2]]], item.id, v[5])
            } else if ((item[v[2]] || '').length >= v[3]) {
              tempCom = (
                <span style={{ cursor: 'pointer' }} title={item[v[2]]}>
                  {tempCom}
                </span>
              )
            }

            return tempCom
          },
          input: (item: any) => {
            return (
              <Form.Item noStyle name={`${item.id}-${v[2]}`}>
                <Input
                  allowClear
                  readOnly={readOnly}
                  maxLength={v[3]?.maxLength}
                  placeholder={v[3]?.placeholder || '请输入'}
                />
              </Form.Item>
            )
          },
          datePicker: (item: any) => {
            return (
              <Form.Item noStyle name={`${item.id}-${v[2]}`}>
                <DatePicker disabled={readOnly} {...(v[3] || {})} />
              </Form.Item>
            )
          },
          custom: (item: any) => {
            return (
              <Form.Item noStyle name={`${item.id}-${v[2]}`} initialValue={item[v[2]]}>
                {v[3].render(readOnly, item)}
              </Form.Item>
            )
          },
          desensitize: (item: any) => {
            const txt = item[v[2]]
            if (!txt) return isNull
            const frontLen = v[3]?.frontLen || 3
            const endLen = v[3]?.endLen || 4

            return getDesensitizeTxt(txt, frontLen, endLen)
          },
          select: (item: any) => {
            let txt = isNull
            const data = v[3]
            const id = item[v[2]]
            const obj = data.find((v: any) => v.value === id)
            if (obj) txt = obj.label
            return txt
          },
          connectTxt: (item: any) => {
            const txt1 = v[2] ? item[v[2]] || isNull : isNull
            const txt2 = v[3] ? item[v[3]] || isNull : isNull
            console.log(txt1, txt2, item[v[2]], item[v[3]])
            return !item[v[2]] && !item[v[3]] ? isNull : `${txt1}-${txt2}`
          }
        }

        return Reflect.get(obj, v[0])
      },
      [isNull, pageNum, pageSize, readOnly, tableComObj]
    )

    const columns = useMemo(() => {
      const arr: any = columnsTemp.map((v: any) => ({
        title: myTitle && v.includes(myTitle.name) ? myTitle.Com : v[1],
        render: dataChangeFu(v),
        width: widthSet && Reflect.get(widthSet, v[2]) ? Reflect.get(widthSet, v[2]) : 'auto',
        onCell:
          merge && v.includes(merge.type)
            ? // {rowSpan:3}
              (item: any, index: number) => ({
                rowSpan: index === 0 ? merge.num : 0
              })
            : ''
      }))

      return arr
    }, [columnsTemp, dataChangeFu, merge, myTitle, widthSet])

    useImperativeHandle(ref, () => ({
      form
    }))

    return (
      <Form form={form} component={false}>
        <Table
          className={classNames(
            `${styles.MyTable} MyTable${classKey}`,
            emptyText ? styles.MyTableNull : ''
          )}
          scroll={{ y: yHeight ? yHeight : '' }}
          dataSource={list}
          columns={[...startBtn, ...columns, ...lastBtn]}
          rowKey={rowKey ? rowKey : 'id'}
          pagination={
            pagingInfo
              ? {
                  ...pagingInfo,
                  current: pageNum,
                  pageSize: pageSize,
                  total: total,
                  onChange: paginationChange()
                }
              : false
          }
          {...rest}
        />
      </Form>
    )
  }
)

const MemoMyTable = React.memo(MyTable)

export default MemoMyTable
