// src/pages/story/detail.tsx
import AddTimeLineItemModal from '@/pages/story/components/AddTimeLineItemModal';
import TimelineItem from '@/pages/story/components/TimelineItem/TimelineItem';
import { StoryItem, StoryItemTimeQueryParams } from '@/pages/story/data';
import { queryStoryDetail, queryStoryItem } from '@/pages/story/service';
import { PlusOutlined, SyncOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { history, useRequest } from '@umijs/max';
import { Button, Empty, FloatButton, message, Spin } from 'antd';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import AutoSizer from 'react-virtualized-auto-sizer';
import { VariableSizeList as List } from 'react-window';
import './index.css';

// 格式化时间数组为易读格式
const formatTimeArray = (time: string | number[] | undefined): string => {
  if (!time) return '';
  
  // 如果是数组格式 [2025, 12, 23, 8, 55, 39]
  if (Array.isArray(time)) {
    const [year, month, day, hour, minute, second] = time;
    return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`;
  }
  
  // 如果已经是字符串格式，直接返回
  return String(time);
};

const Index = () => {
  const { id: lineId } = useParams<{ id: string }>();
  const containerRef = useRef<HTMLDivElement>(null);
  const listRef = useRef<any>(null);
  const outerRef = useRef<HTMLDivElement>(null);
  const topSentinelRef = useRef<HTMLDivElement>(null);
  const bottomSentinelRef = useRef<HTMLDivElement>(null);
  const [items, setItems] = useState<StoryItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [hasMoreOld, setHasMoreOld] = useState(true); // 是否有更老的数据
  const [hasMoreNew, setHasMoreNew] = useState(true); // 是否有更新的数据
  const [openAddItemModal, setOpenAddItemModal] = useState(false);
  const [currentItem, setCurrentItem] = useState<StoryItem>();
  const [currentOption, setCurrentOption] = useState<
    'add' | 'edit' | 'addSubItem' | 'editSubItem'
  >();
  const [pagination, setPagination] = useState({ current: 1, pageSize: 10 });
  // 存储每个item的高度
  const [itemSizes, setItemSizes] = useState<Record<string, number>>({});
  // 存储已测量高度的item ID集合
  const measuredItemsRef = useRef<Set<string>>(new Set());
  const [isRefreshing, setIsRefreshing] = useState(false); // 是否正在刷新最新数据
  const [showScrollTop, setShowScrollTop] = useState(false); // 是否显示回到顶部按钮
  const [currentTimeArr, setCurrentTimeArr] = useState<[string | undefined, string | undefined]>([
    undefined,
    undefined,
  ]);
  const [loadDirection, setLoadDirection] = useState<'init' | 'older' | 'newer' | 'refresh'>(
    'init',
  );
// 添加在其他 useRef 之后
  const hasShownNoMoreOldRef = useRef(false);
  const hasShownNoMoreNewRef = useRef(false);
  const topLoadingRef = useRef(false); // 防止顶部循环加载

  type QueryParams = StoryItemTimeQueryParams & { current?: number; pageSize?: number };

  const { data: response, run } = useRequest(
    (params?: QueryParams) => {
      return queryStoryItem({ storyInstanceId: lineId, pageSize: pagination.pageSize, ...params });
    },
    {
      manual: true,
    },
  );

  const {
    data: detail,
    run: queryDetail,
    loading: queryDetailLoading,
  } = useRequest(() => {
    return queryStoryDetail(lineId ?? '');
  });

  // 初始化加载数据
  useEffect(() => {
    setHasMoreOld(true);
    setHasMoreNew(true);
    // 重置高度缓存
    setItemSizes({});
    measuredItemsRef.current = new Set();
    setLoadDirection('init');
    setLoading(true);
    run({ current: 1 });
  }, [lineId]);
  // 处理响应数据
  useEffect(() => {
    if (!response) return;
    const fetched = response.list || [];
    const pageSize = pagination.pageSize;
    const noMore = !(fetched.length === pageSize);

    // 若无新数据则避免触发列表重绘，只更新加载状态
    if (!fetched.length) {
      if (loadDirection === 'older') {
        setHasMoreOld(false);
      } else if (loadDirection === 'newer') {
        setHasMoreNew(false);
        topLoadingRef.current = false;
      }
      setLoading(false);
      setIsRefreshing(false);
      setLoadDirection('init');
      return;
    }

    if (loadDirection === 'older') {
      setItems((prev) => {
        const next = [...prev, ...fetched];
        setCurrentTimeArr([next[0]?.storyItemTime, next[next.length - 1]?.storyItemTime]);
        return next;
      });
      setHasMoreOld(!noMore);
      if (noMore && !hasShownNoMoreOldRef.current) {
        hasShownNoMoreOldRef.current = true;
        message.info('没有更多历史内容了');
      }
    } else if (loadDirection === 'newer') {
      setItems((prev) => {
        const next = [...fetched, ...prev];
        setCurrentTimeArr([next[0]?.storyItemTime, next[next.length - 1]?.storyItemTime]);
        if (listRef.current && fetched.length) {
          requestAnimationFrame(() => listRef.current?.scrollToItem(fetched.length + 1, 'start'));
        }
        return next;
      });
      setHasMoreNew(!noMore);
      if (noMore && !hasShownNoMoreNewRef.current) {
        hasShownNoMoreNewRef.current = true;
        message.info('没有更多更新内容了');
      }
      topLoadingRef.current = false;
    } else if (loadDirection === 'refresh') {
      topLoadingRef.current = false;
    } else {
      setItems(fetched);
      setCurrentTimeArr([fetched[0]?.storyItemTime, fetched[fetched.length - 1]?.storyItemTime]);
      setHasMoreOld(!noMore);
      setHasMoreNew(true);
    }

    setLoading(false);
    setIsRefreshing(false);
    setLoadDirection('init');
  }, [response, loadDirection, pagination.pageSize]);

  // 获取item高度的函数
  const getItemSize = useCallback(
    (index: number) => {
    const item = items[index];
    if (!item) return 400; // 默认高度
    const key = String(item.id ?? item.instanceId);

    if (itemSizes[key]) {
      return itemSizes[key];
    }

    return 400;
    },
    [items, itemSizes, loadDirection, loading],
  );

  // 当item尺寸发生变化时调用
  const onItemResize = useCallback(
    (itemId: string, height: number) => {
    // 只有当高度发生变化时才更新
    if (itemSizes[itemId] !== height) {
        setItemSizes((prev) => ({
        ...prev,
          [itemId]: height,
      }));

      // 通知List组件重新计算尺寸
      if (listRef.current) {
        listRef.current.resetAfterIndex(0);
      }
    }
    },
    [itemSizes],
  );
  // 滚动到底部加载更老的数据
  const loadOlder = useCallback(() => {
    if (loading || !hasMoreOld) {
      if (!hasMoreOld && !loading) {
        message.info('没有更多历史内容了');
      }
      return;
    }
    const beforeTime = items[items.length - 1]?.storyItemTime || currentTimeArr[1];
    if (!beforeTime) return;
    const nextPage = pagination.current + 1;
    setPagination((prev) => ({ ...prev, current: nextPage }));
    setLoadDirection('older');
    setLoading(true);
    run({ current: nextPage });
  }, [loading, hasMoreOld, items, currentTimeArr, pagination.current, run]);

// 滚动到顶部加载更新的数据
  const loadNewer = useCallback(() => {
    if (loading || !hasMoreNew || isRefreshing || topLoadingRef.current) {
      if (!hasMoreNew && !loading && !isRefreshing) {
        message.info('没有更多更新内容了');
      }
      return;
    }

    const afterTime = items[0]?.storyItemTime || currentTimeArr[0];
    if (!afterTime) return;
    setPagination((prev) => ({ ...prev, current: 1 }));
    setLoadDirection('newer');
    setIsRefreshing(true);
    setLoading(true);
    topLoadingRef.current = true;
    run({ current: 1 });
  }, [loading, hasMoreNew, isRefreshing, items, currentTimeArr, run]);

  // 渲染单个时间线项的函数
  const renderTimelineItem = useCallback(
    ({ index, style }: { index: number; style: React.CSSProperties }) => {
      const item = items[index];
      if (!item) return null;
      const key = String(item.id ?? item.instanceId);

      return (
        <div style={style}>
          <div
            ref={(el) => {
              // 当元素被渲染时测量其实际高度
              if (el && !measuredItemsRef.current.has(key)) {
                measuredItemsRef.current.add(key);
                // 使用requestAnimationFrame确保DOM已经渲染完成
                requestAnimationFrame(() => {
                  if (el) {
                    const height = el.getBoundingClientRect().height;
                    onItemResize(key, height);
                  }
                });
              }
            }}
            style={{
              margin: '12px 0',
              padding: '16px',
              backgroundColor: '#fff',
              borderRadius: '8px',
              boxShadow: '0 1px 4px rgba(0,0,0,0.05)',
              border: '1px solid #f0f0f0',
              transition: 'all 0.2s ease-in-out',
            }}
            onMouseEnter={(e) => {
              (e.currentTarget as HTMLDivElement).style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
              (e.currentTarget as HTMLDivElement).style.transform = 'translateY(-2px)';
            }}
            onMouseLeave={(e) => {
              (e.currentTarget as HTMLDivElement).style.boxShadow = '0 1px 4px rgba(0,0,0,0.05)';
              (e.currentTarget as HTMLDivElement).style.transform = 'translateY(0)';
            }}
          >
            <TimelineItem
              item={item}
              handleOption={(
                item: StoryItem,
                option: 'add' | 'edit' | 'addSubItem' | 'editSubItem',
              ) => {
                setCurrentItem(item);
                setCurrentOption(option);
                setOpenAddItemModal(true);
              }}
              refresh={() => {
                // 刷新当前页数据
                setPagination((prev) => ({ ...prev, current: 1 }));
                // 重置高度测量
                measuredItemsRef.current = new Set();
                hasShownNoMoreOldRef.current = false;
                hasShownNoMoreNewRef.current = false;
                setLoadDirection('refresh');
                run({ current: 1 });
                queryDetail();
              }}
            />
          </div>
        </div>
      );
    },
    [items, hasMoreOld, loadDirection, loading, onItemResize, run, queryDetail],
  );

  // 使用 IntersectionObserver 监听顶部/底部哨兵实现无限滚动
  useEffect(() => {
    const root = outerRef.current;
    const topEl = topSentinelRef.current;
    const bottomEl = bottomSentinelRef.current;
    if (!root || !topEl || !bottomEl) return;

    const topObserver = new IntersectionObserver(
      (entries) => {
        if (entries.some((e) => e.isIntersecting)) {
          loadNewer();
        }
      },
      { root, rootMargin: '120px 0px 0px 0px', threshold: 0 },
    );

    const bottomObserver = new IntersectionObserver(
      (entries) => {
        if (entries.some((e) => e.isIntersecting)) {
          loadOlder();
        }
      },
      { root, rootMargin: '0px 0px 120px 0px', threshold: 0 },
    );

    topObserver.observe(topEl);
    bottomObserver.observe(bottomEl);

    // 仅用于显示"回到顶部"按钮
    const handleScroll = () => {
      const { scrollTop } = root;
      setShowScrollTop(scrollTop > 200);
    };
    root.addEventListener('scroll', handleScroll);

    return () => {
      topObserver.disconnect();
      bottomObserver.disconnect();
      root.removeEventListener('scroll', handleScroll);
    };
  }, [loadNewer, loadOlder]);

  // 手动刷新最新数据
  const handleRefresh = () => {
    if (isRefreshing) return;

    setIsRefreshing(true);
    setLoadDirection('refresh');
    setPagination((prev) => ({ ...prev, current: 1 }));
    hasShownNoMoreOldRef.current = false;
    hasShownNoMoreNewRef.current = false;
    run({ current: 1 });
  };

  // 回到顶部
  const scrollToTop = () => {
    if (listRef.current) {
      listRef.current.scrollToItem(0, 'start');
    }
  };

  return (
    <PageContainer
      onBack={() => history.push('/story')}
      title={
        queryDetailLoading ? '加载中' : `${detail?.title} ${`共${detail?.itemCount ?? 0}个时刻`}`
      }
      extra={
        <Button
          icon={<SyncOutlined />}
          onClick={() => {
            setItems([]);
            setPagination({ current: 1, pageSize: 10 });
            setLoadDirection('refresh');
            run({ current: 1 });
          }}
          loading={isRefreshing}
        >
          刷新
        </Button>
      }
    >
      <div
        className="timeline"
        ref={containerRef}
        style={{
          height: 'calc(100vh - 200px)',
          overflow: 'hidden',
          position: 'relative',
          padding: '0 16px', // 添加一些内边距
        }}
      >
        {items.length > 0 ? (
          <>
            <AutoSizer>
              {({ height, width }) => (
                <>
                <List
                  ref={listRef}
                    outerRef={outerRef}
                    height={height}
                    itemCount={items.length}
                  itemSize={getItemSize}
                  width={width}
                    innerElementType={React.forwardRef<
                      HTMLDivElement,
                      React.HTMLAttributes<HTMLDivElement>
                    >((props, ref) => (
                      <div ref={ref} {...props}>
                        <div ref={topSentinelRef} style={{ height: 1 }} />
                        {props.children}
                        <div ref={bottomSentinelRef} style={{ height: 1 }} />
                      </div>
                    ))}
                >
                  {renderTimelineItem}
                </List>
                  <div className="load-indicator">{loading && '加载中...'}</div>
                  <div className="no-more-data">{!loading && '已加载全部历史数据'}</div>
                </>
              )}
            </AutoSizer>
            {/* 回到顶部按钮 */}
            {showScrollTop && (
              <div
                style={{
                position: 'absolute',
                bottom: 20,
                right: 20,
                zIndex: 10,
                }}
              >
                <Button
                  type="primary"
                  shape="circle"
                  icon={<SyncOutlined />}
                  onClick={scrollToTop}
                />
              </div>
            )}
          </>
        ) : (
          <div
            style={{
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center',
            height: '100%',
              textAlign: 'center',
            }}
          >
            {loading ? (
              <>
                <Spin size="large" />
                <div
                  style={{
                  marginTop: 16,
                  fontSize: '16px',
                    color: '#666',
                  }}
                >
                  正在加载时间线数据...
                </div>
              </>
            ) : (
                <>
                  <Empty
                    description="暂无时间线数据"
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    imageStyle={{
                      height: 60,
                    }}
                  >
                  <div
                    style={{
                      fontSize: '16px',
                      color: '#999',
                      marginBottom: '16px',
                    }}
                  >
                      还没有添加任何时刻
                    </div>
                  </Empty>
                  <Button
                    type="primary"
                    size="large"
                    onClick={() => {
                      setCurrentOption('add');
                      setCurrentItem(undefined);
                      setOpenAddItemModal(true);
                    }}
                  >
                    添加第一个时刻
                  </Button>
                </>
            )}
          </div>
        )}
      </div>
      <FloatButton
        onClick={() => {
          setCurrentOption('add');
          setCurrentItem(undefined);
          setOpenAddItemModal(true);
        }}
        icon={<PlusOutlined />}
        type="primary"
        style={{
          right: 24,
          bottom: 24,
        }}
      />

      <AddTimeLineItemModal
        visible={openAddItemModal}
        initialValues={currentItem}
        option={currentOption || 'add'}
        onCancel={() => {
          setOpenAddItemModal(false);
        }}
        onOk={() => {
          setOpenAddItemModal(false);
          // 添加新项后刷新数据
          setPagination((prev) => ({ ...prev, current: 1 }));
          // 重置高度测量
          measuredItemsRef.current = new Set();
          setLoadDirection('refresh');
          run({ current: 1 });
          queryDetail();
        }}
        storyId={lineId}
      />
    </PageContainer>
  );
};

export default Index;