import React, {
  CSSProperties,
  UIEvent,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import VirtualList from 'rc-virtual-list';
import { formatMoneyNumber, formatToPercentage } from '@/utils/format';

type AnyColumn = {
  title?: any;
  dataIndex?: string | number;
  key?: string;
  width?: number;
  align?: 'left' | 'center' | 'right';
  children?: AnyColumn[];
};

type BodyInfo = {
  scrollbarSize: number;
  ref: any;
  onScroll: (params: { scrollLeft?: number; scrollTop?: number }) => void;
};

function flattenLeafColumns(columns: AnyColumn[]): AnyColumn[] {
  const leaves: AnyColumn[] = [];
  const walk = (cols: AnyColumn[]) => {
    (cols || []).forEach((c) => {
      if (Array.isArray(c.children) && c.children.length > 0) {
        walk(c.children);
      } else {
        leaves.push(c);
      }
    });
  };
  walk(columns || []);
  return leaves;
}

export function buildVirtualBody(options: {
  columns: AnyColumn[];
  rowHeight?: number;
  height: number;
  width: number;
}) {
  const { columns, rowHeight = 44, height, width } = options;

  const leafColumns = flattenLeafColumns(columns);
  const columnWidths = leafColumns.map((c) =>
    typeof c.width === 'number' ? c.width : 120,
  );

  const VirtualBody: React.FC<{ rawData: any[]; info: BodyInfo }> = ({
    rawData,
    info,
  }) => {
    // 外层滚动容器（承担横向滚动同步）
    const outerRef = useRef<HTMLDivElement | null>(null);
    const listRef = useRef<any>(null);

    const [connectObject] = useState(() => {
      const obj: any = {};
      Object.defineProperty(obj, 'scrollLeft', {
        get: () => null,
        set: (scrollLeft: number) => {
          if (outerRef.current) {
            outerRef.current.scrollLeft = scrollLeft;
          }
        },
      });
      return obj;
    });

    useEffect(() => {
      if (info && info.ref) {
        info.ref.current = connectObject;
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [rawData, leafColumns.length, height, width]);

    const getColumnWidth = (index: number) => columnWidths[index] || 120;

    const cellStyleBase: CSSProperties = useMemo(
      () => ({
        boxSizing: 'border-box',
        padding: '8px 8px',
        borderTop: '1px solid rgb(218 226 242)',
        overflow: 'hidden',
        whiteSpace: 'nowrap',
        textOverflow: 'ellipsis',
      }),
      [],
    );

    const Row = ({ index }: { index: number; style?: CSSProperties }) => {
      const record = rawData[index] || {};
      return (
        <div className="virtual-table-row" style={{ width, display: 'flex' }}>
          {leafColumns.map((col, columnIndex) => {
            const dataIndex = col?.dataIndex as any;
            const raw = record?.[dataIndex];
            const align = col?.align || 'left';
            const w = getColumnWidth(columnIndex);
            // 统一渲染：优先使用列自带的 renderText；否则根据标题或 dataIndex 判断金额/占比
            let text: any = raw;
            try {
              const titleStr = typeof col?.title === 'string' ? col.title : '';
              const isRatio =
                String(dataIndex || '')
                  .toLowerCase()
                  .endsWith('ratio') || String(titleStr).includes('占比');
              if (typeof (col as any).renderText === 'function') {
                text = (col as any).renderText(raw, record);
              } else if (isRatio) {
                text = formatToPercentage(raw);
              } else if (typeof raw === 'number') {
                text = formatMoneyNumber(raw, {
                  decimalPlaces: 2,
                  useThousandSeparator: true,
                });
              }
            } catch {}
            return (
              <div
                key={String(col.key || dataIndex || columnIndex)}
                className="virtual-table-cell"
                style={{
                  ...cellStyleBase,
                  textAlign: align as any,
                  width: w,
                  flex: '0 0 auto',
                }}
              >
                {text as any}
              </div>
            );
          })}
        </div>
      );
    };

    const handleScroll = (e: UIEvent<HTMLDivElement>) => {
      const target = e.currentTarget;
      info?.onScroll?.({ scrollLeft: target.scrollLeft });
    };

    const handleWheelCapture = (e: React.WheelEvent<HTMLDivElement>) => {
      // 将横向滚动手势映射到外层容器，实现“在中间区域也能横向滚动”
      if (!outerRef.current) return;
      const hasHorizontal = Math.abs(e.deltaX) > 0 || e.shiftKey;
      if (!hasHorizontal) return;
      const container = outerRef.current;
      const max = (container.scrollWidth || 0) - (container.clientWidth || 0);
      if (max <= 0) return;
      const next = Math.max(
        0,
        Math.min(
          max,
          container.scrollLeft + (e.deltaX || (e.deltaY > 0 ? 40 : -40)),
        ),
      );
      if (next !== container.scrollLeft) {
        container.scrollLeft = next;
        try {
          info?.onScroll?.({ scrollLeft: next });
        } catch {}
        e.preventDefault();
      }
    };

    return (
      <div
        style={{ width: '100%', overflowX: 'auto' }}
        ref={outerRef}
        onScroll={handleScroll}
        onWheelCapture={handleWheelCapture}
      >
        <div style={{ width }}>
          <VirtualList
            ref={listRef}
            data={rawData}
            height={height}
            itemHeight={rowHeight}
            itemKey={(item: any, idx: number) =>
              String(item?.id ?? item?.key ?? idx)
            }
            style={{ overflowX: 'hidden' }}
            onScroll={(e: any) => {
              try {
                info?.onScroll?.({ scrollTop: e.scrollTop });
              } catch {}
            }}
          >
            {(item: any, index: number) => <Row index={index} />}
          </VirtualList>
        </div>
      </div>
    );
  };

  // antd Table 期望的 components.body 签名：(rawData, info) => ReactNode
  return (rawData: any[], info: BodyInfo) => {
    return <VirtualBody rawData={rawData} info={info} />;
  };
}

export default buildVirtualBody;
