// src/components/StockChart/KLineChartModal.tsx - K线图弹窗组件
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { createPortal } from 'react-dom';
import { useSelector } from 'react-redux';
import * as echarts from 'echarts';
import dayjs from 'dayjs';
import { stockService } from '@services/eventService';
import { selectIsMobile } from '@store/slices/deviceSlice';

/**
 * 股票信息
 */
interface StockInfo {
  stock_code: string;
  stock_name?: string;
}

/**
 * KLineChartModal 组件 Props
 */
export interface KLineChartModalProps {
  /** 模态框是否打开 */
  isOpen: boolean;
  /** 关闭回调 */
  onClose: () => void;
  /** 股票信息 */
  stock: StockInfo | null;
  /** 事件时间 */
  eventTime?: string | null;
  /** 模态框大小 */
  size?: string;
}

/**
 * K线数据点
 */
interface KLineDataPoint {
  time: string;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}

/**
 * 批量K线API响应
 */
interface BatchKlineResponse {
  success: boolean;
  data: {
    [stockCode: string]: {
      code: string;
      name: string;
      data: KLineDataPoint[];
      trade_date: string;
      type: string;
      earliest_date?: string;
    };
  };
  has_more: boolean;
  query_start_date?: string;
  query_end_date?: string;
}

// 每次加载的天数
const DAYS_PER_LOAD = 60;
// 最大加载天数（一年）
const MAX_DAYS = 365;

const KLineChartModal: React.FC<KLineChartModalProps> = ({
  isOpen,
  onClose,
  stock,
  eventTime,
  size = '5xl',
}) => {
  const chartRef = useRef<HTMLDivElement>(null);
  const chartInstance = useRef<echarts.ECharts | null>(null);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [data, setData] = useState<KLineDataPoint[]>([]);
  const [hasMore, setHasMore] = useState(true);
  const [earliestDate, setEarliestDate] = useState<string | null>(null);
  const [totalDaysLoaded, setTotalDaysLoaded] = useState(0);

  // H5 响应式适配
  const isMobile = useSelector(selectIsMobile);

  // 调试日志
  console.log('[KLineChartModal] 渲染状态:', {
    isOpen,
    stock,
    eventTime,
    dataLength: data.length,
    loading,
    loadingMore,
    hasMore,
    earliestDate
  });

  // 加载更多历史数据
  const loadMoreData = useCallback(async () => {
    if (!stock?.stock_code || !hasMore || loadingMore || !earliestDate) return;

    console.log('[KLineChartModal] 加载更多历史数据, earliestDate:', earliestDate);
    setLoadingMore(true);

    try {
      const stableEventTime = eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : '';

      // 请求更早的数据，end_date 设置为当前最早日期的前一天
      const endDate = dayjs(earliestDate).subtract(1, 'day').format('YYYY-MM-DD');

      const response = await stockService.getBatchKlineData(
        [stock.stock_code],
        'daily',
        stableEventTime,
        { days_before: DAYS_PER_LOAD, end_date: endDate }
      ) as BatchKlineResponse;

      if (response?.success && response.data) {
        const stockData = response.data[stock.stock_code];
        const newData = stockData?.data || [];

        if (newData.length > 0) {
          // 将新数据添加到现有数据的前面
          setData(prevData => [...newData, ...prevData]);
          setEarliestDate(newData[0].time);
          setTotalDaysLoaded(prev => prev + DAYS_PER_LOAD);
          console.log('[KLineChartModal] 加载了更多数据:', newData.length, '条');
        }

        // 检查是否还有更多数据
        const noMoreData = !response.has_more || totalDaysLoaded + DAYS_PER_LOAD >= MAX_DAYS || newData.length === 0;
        setHasMore(!noMoreData);
      }
    } catch (err) {
      console.error('[KLineChartModal] 加载更多数据失败:', err);
    } finally {
      setLoadingMore(false);
    }
  }, [stock?.stock_code, hasMore, loadingMore, earliestDate, eventTime, totalDaysLoaded]);

  // 初始加载K线数据
  const loadData = useCallback(async () => {
    if (!stock?.stock_code) return;

    setLoading(true);
    setError(null);
    setData([]);
    setHasMore(true);
    setEarliestDate(null);
    setTotalDaysLoaded(0);

    try {
      const stableEventTime = eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : '';

      // 使用新的带分页参数的接口
      const response = await stockService.getBatchKlineData(
        [stock.stock_code],
        'daily',
        stableEventTime,
        { days_before: DAYS_PER_LOAD, end_date: '' }
      ) as BatchKlineResponse;

      if (response?.success && response.data) {
        const stockData = response.data[stock.stock_code];
        const klineData = stockData?.data || [];

        if (klineData.length === 0) {
          throw new Error('暂无K线数据');
        }

        console.log('[KLineChartModal] 初始数据条数:', klineData.length);
        setData(klineData);
        setEarliestDate(klineData[0]?.time || null);
        setTotalDaysLoaded(DAYS_PER_LOAD);
        setHasMore(response.has_more !== false);
      } else {
        throw new Error('数据加载失败');
      }
    } catch (err) {
      const errorMsg = err instanceof Error ? err.message : '数据加载失败';
      setError(errorMsg);
    } finally {
      setLoading(false);
    }
  }, [stock?.stock_code, eventTime]);

  // 用于防抖的 ref
  const loadMoreDebounceRef = useRef<NodeJS.Timeout | null>(null);

  // 初始化图表
  useEffect(() => {
    if (!isOpen) return;

    // 延迟初始化，确保 Modal 动画完成后 DOM 已经渲染
    const timer = setTimeout(() => {
      if (!chartRef.current) {
        console.error('[KLineChartModal] DOM元素未找到，无法初始化图表');
        return;
      }

      console.log('[KLineChartModal] 初始化图表...');

      // 创建图表实例（不使用主题，直接在option中配置背景色）
      chartInstance.current = echarts.init(chartRef.current);

      console.log('[KLineChartModal] 图表实例创建成功');

      // 监听窗口大小变化
      const handleResize = () => {
        chartInstance.current?.resize();
      };
      window.addEventListener('resize', handleResize);

      return () => {
        window.removeEventListener('resize', handleResize);
      };
    }, 100); // 延迟100ms等待Modal完全打开

    return () => {
      clearTimeout(timer);
      if (loadMoreDebounceRef.current) {
        clearTimeout(loadMoreDebounceRef.current);
      }
      if (chartInstance.current) {
        chartInstance.current.dispose();
        chartInstance.current = null;
      }
    };
  }, [isOpen]);

  // 监听 dataZoom 事件，当滑到左边界时加载更多数据
  useEffect(() => {
    if (!chartInstance.current || !hasMore || loadingMore) return;

    const handleDataZoom = (params: any) => {
      // 获取当前 dataZoom 的 start 值
      const start = params.start ?? params.batch?.[0]?.start ?? 0;

      // 当 start 接近 0（左边界）时，触发加载更多
      if (start <= 5 && hasMore && !loadingMore) {
        console.log('[KLineChartModal] 检测到滑动到左边界，准备加载更多数据');

        // 防抖处理
        if (loadMoreDebounceRef.current) {
          clearTimeout(loadMoreDebounceRef.current);
        }
        loadMoreDebounceRef.current = setTimeout(() => {
          loadMoreData();
        }, 300);
      }
    };

    chartInstance.current.on('datazoom', handleDataZoom);

    return () => {
      chartInstance.current?.off('datazoom', handleDataZoom);
    };
  }, [hasMore, loadingMore, loadMoreData]);

  // 更新图表数据
  useEffect(() => {
    if (data.length === 0) {
      console.log('[KLineChartModal] 无数据，跳过图表更新');
      return;
    }

    const updateChart = () => {
      if (!chartInstance.current) {
        console.warn('[KLineChartModal] 图表实例不存在');
        return false;
      }

      console.log('[KLineChartModal] 开始更新图表，数据点:', data.length);

    const dates = data.map((d) => d.time);
    const klineData = data.map((d) => [d.open, d.close, d.low, d.high]);
    const volumes = data.map((d) => d.volume);

    // 计算成交量柱子颜色（涨为红，跌为绿）
    const volumeColors = data.map((d) =>
      d.close >= d.open ? '#ef5350' : '#26a69a'
    );

    // 提取事件发生日期（YYYY-MM-DD格式）
    let eventDateStr: string | null = null;
    if (eventTime) {
      try {
        const eventDate = new Date(eventTime);
        const year = eventDate.getFullYear();
        const month = (eventDate.getMonth() + 1).toString().padStart(2, '0');
        const day = eventDate.getDate().toString().padStart(2, '0');
        eventDateStr = `${year}-${month}-${day}`;
        console.log('[KLineChartModal] 事件发生日期:', eventDateStr);
      } catch (e) {
        console.error('[KLineChartModal] 解析事件日期失败:', e);
      }
    }

    // 图表配置（H5 响应式）
    const option: echarts.EChartsOption = {
      backgroundColor: '#1a1a1a',
      title: {
        text: `${stock?.stock_name || stock?.stock_code} - 日K线`,
        left: 'center',
        top: isMobile ? 5 : 10,
        textStyle: {
          color: '#e0e0e0',
          fontSize: isMobile ? 14 : 18,
          fontWeight: 'bold',
        },
      },
      tooltip: {
        trigger: 'axis',
        backgroundColor: 'rgba(30, 30, 30, 0.95)',
        borderColor: '#404040',
        borderWidth: 1,
        textStyle: {
          color: '#e0e0e0',
        },
        axisPointer: {
          type: 'cross',
          crossStyle: {
            color: '#999',
          },
        },
        formatter: (params: any) => {
          const dataIndex = params[0]?.dataIndex;
          if (dataIndex === undefined) return '';

          const item = data[dataIndex];
          const change = item.close - item.open;
          const changePercent = (change / item.open) * 100;
          const changeColor = change >= 0 ? '#ef5350' : '#26a69a';
          const changeSign = change >= 0 ? '+' : '';

          return `
            <div style="padding: 8px;">
              <div style="font-weight: bold; margin-bottom: 8px;">${item.time}</div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>开盘:</span>
                <span style="margin-left: 20px;">${item.open.toFixed(2)}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>收盘:</span>
                <span style="color: ${changeColor}; font-weight: bold; margin-left: 20px;">${item.close.toFixed(2)}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>最高:</span>
                <span style="margin-left: 20px;">${item.high.toFixed(2)}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>最低:</span>
                <span style="margin-left: 20px;">${item.low.toFixed(2)}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>涨跌额:</span>
                <span style="color: ${changeColor}; margin-left: 20px;">${changeSign}${change.toFixed(2)}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
                <span>涨跌幅:</span>
                <span style="color: ${changeColor}; margin-left: 20px;">${changeSign}${changePercent.toFixed(2)}%</span>
              </div>
              <div style="display: flex; justify-content: space-between;">
                <span>成交量:</span>
                <span style="margin-left: 20px;">${(item.volume / 100).toFixed(0)}手</span>
              </div>
            </div>
          `;
        },
      },
      grid: [
        {
          left: isMobile ? '12%' : '5%',
          right: isMobile ? '5%' : '5%',
          top: isMobile ? '12%' : '12%',
          height: isMobile ? '55%' : '60%',
        },
        {
          left: isMobile ? '12%' : '5%',
          right: isMobile ? '5%' : '5%',
          top: isMobile ? '72%' : '77%',
          height: isMobile ? '20%' : '18%',
        },
      ],
      xAxis: [
        {
          type: 'category',
          data: dates,
          gridIndex: 0,
          axisLine: {
            lineStyle: {
              color: '#404040',
            },
          },
          axisLabel: {
            color: '#999',
            fontSize: isMobile ? 10 : 12,
            interval: Math.floor(dates.length / (isMobile ? 4 : 8)),
          },
          splitLine: {
            show: false,
          },
        },
        {
          type: 'category',
          data: dates,
          gridIndex: 1,
          axisLine: {
            lineStyle: {
              color: '#404040',
            },
          },
          axisLabel: {
            color: '#999',
            fontSize: isMobile ? 10 : 12,
            interval: Math.floor(dates.length / (isMobile ? 4 : 8)),
          },
        },
      ],
      yAxis: [
        {
          scale: true,
          gridIndex: 0,
          splitNumber: isMobile ? 4 : 5,
          splitLine: {
            show: true,
            lineStyle: {
              color: '#2a2a2a',
            },
          },
          axisLine: {
            lineStyle: {
              color: '#404040',
            },
          },
          axisLabel: {
            color: '#999',
            fontSize: isMobile ? 10 : 12,
            formatter: (value: number) => value.toFixed(2),
          },
        },
        {
          scale: true,
          gridIndex: 1,
          splitNumber: isMobile ? 2 : 3,
          splitLine: {
            show: false,
          },
          axisLine: {
            lineStyle: {
              color: '#404040',
            },
          },
          axisLabel: {
            color: '#999',
            fontSize: isMobile ? 10 : 12,
            formatter: (value: number) => {
              if (value >= 100000000) {
                return (value / 100000000).toFixed(1) + '亿';
              } else if (value >= 10000) {
                return (value / 10000).toFixed(1) + '万';
              }
              return value.toFixed(0);
            },
          },
        },
      ],
      series: [
        {
          name: 'K线',
          type: 'candlestick',
          data: klineData,
          xAxisIndex: 0,
          yAxisIndex: 0,
          itemStyle: {
            color: '#ef5350', // 涨
            color0: '#26a69a', // 跌
            borderColor: '#ef5350',
            borderColor0: '#26a69a',
          },
          markLine: eventDateStr ? {
            silent: false,
            symbol: 'none',
            label: {
              show: true,
              position: 'insideEndTop',
              formatter: '事件发生',
              color: '#ffd700',
              fontSize: 12,
              fontWeight: 'bold',
              backgroundColor: 'rgba(0, 0, 0, 0.7)',
              padding: [4, 8],
              borderRadius: 4,
            },
            lineStyle: {
              color: '#ffd700',
              width: 2,
              type: 'solid',
            },
            data: [
              {
                xAxis: eventDateStr,
                label: {
                  formatter: '⚡ 事件发生',
                },
              },
            ],
          } : undefined,
        },
        {
          name: '成交量',
          type: 'bar',
          data: volumes,
          xAxisIndex: 1,
          yAxisIndex: 1,
          itemStyle: {
            color: (params: any) => {
              return volumeColors[params.dataIndex];
            },
          },
        },
      ],
      dataZoom: [
        {
          type: 'inside',
          xAxisIndex: [0, 1],
          start: 0,
          end: 100,
        },
      ],
    };

      chartInstance.current.setOption(option);
      console.log('[KLineChartModal] 图表option已设置');

      // 强制resize以确保图表正确显示
      setTimeout(() => {
        chartInstance.current?.resize();
        console.log('[KLineChartModal] 图表已resize');
      }, 100);

      return true;
    };

    // 立即尝试更新，如果失败则重试
    if (!updateChart()) {
      console.log('[KLineChartModal] 第一次更新失败，200ms后重试...');
      const retryTimer = setTimeout(() => {
        updateChart();
      }, 200);

      return () => clearTimeout(retryTimer);
    }
  }, [data, stock, isMobile]);

  // 加载数据
  useEffect(() => {
    if (isOpen) {
      loadData();
    }
  }, [isOpen, stock?.stock_code, eventTime]);

  // 创建或获取 Portal 容器
  useEffect(() => {
    let container = document.getElementById('kline-modal-root');
    if (!container) {
      container = document.createElement('div');
      container.id = 'kline-modal-root';
      container.style.cssText = 'position: fixed; top: 0; left: 0; z-index: 10000;';
      document.body.appendChild(container);
    }
    return () => {
      // 组件卸载时不删除容器，因为可能会被复用
    };
  }, []);

  if (!stock) return null;

  console.log('[KLineChartModal] 渲染 Modal, isOpen:', isOpen);

  // 获取 Portal 容器
  const portalContainer = document.getElementById('kline-modal-root') || document.body;

  // 如果不显示则返回 null
  if (!isOpen) return null;

  const modalContent = (
    <>
      {/* 遮罩层 */}
      <div
        style={{
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          backgroundColor: 'rgba(0, 0, 0, 0.7)',
          zIndex: 10001,
        }}
        onClick={onClose}
      />
      {/* 弹窗内容 */}
      <div
        style={{
          position: 'fixed',
          top: '50%',
          left: '50%',
          transform: 'translate(-50%, -50%)',
          width: isMobile ? '96vw' : '90vw',
          maxWidth: isMobile ? 'none' : '1400px',
          maxHeight: isMobile ? '85vh' : '85vh',
          backgroundColor: '#1a1a1a',
          border: '2px solid #ffd700',
          boxShadow: '0 0 30px rgba(255, 215, 0, 0.5)',
          borderRadius: isMobile ? '12px' : '8px',
          zIndex: 10002,
          display: 'flex',
          flexDirection: 'column',
          overflow: 'hidden',
        }}
      >
        {/* Header */}
        <div
          style={{
            padding: isMobile ? '12px 16px' : '16px 24px',
            borderBottom: '1px solid #404040',
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'flex-start',
          }}
        >
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? '8px' : '12px', flexWrap: isMobile ? 'wrap' : 'nowrap' }}>
              <span style={{ fontSize: isMobile ? '14px' : '18px', fontWeight: 'bold', color: '#e0e0e0' }}>
                {stock.stock_name || stock.stock_code} ({stock.stock_code})
              </span>
              {data.length > 0 && (
                <span style={{ fontSize: isMobile ? '10px' : '12px', color: '#666', fontStyle: 'italic' }}>
                  共{data.length}个交易日
                  {hasMore ? '（向左滑动加载更多）' : '（已加载全部）'}
                </span>
              )}
              {loadingMore && (
                <span style={{ fontSize: isMobile ? '10px' : '12px', color: '#3182ce', display: 'flex', alignItems: 'center', gap: '4px' }}>
                  <span style={{
                    width: '12px',
                    height: '12px',
                    border: '2px solid #404040',
                    borderTop: '2px solid #3182ce',
                    borderRadius: '50%',
                    animation: 'spin 1s linear infinite',
                    display: 'inline-block'
                  }} />
                  加载更多...
                </span>
              )}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? '8px' : '16px', marginTop: '4px' }}>
              <span style={{ fontSize: isMobile ? '12px' : '14px', color: '#999' }}>日K线图</span>
              <span style={{ fontSize: isMobile ? '10px' : '12px', color: '#666' }}>
                💡 {isMobile ? '滚轮缩放 | 拖动查看' : '鼠标滚轮缩放 | 拖动查看不同时间段'}
              </span>
            </div>
          </div>
          <button
            onClick={onClose}
            style={{
              background: 'none',
              border: 'none',
              color: '#999',
              fontSize: '24px',
              cursor: 'pointer',
              padding: '0 8px',
              lineHeight: '1',
            }}
            onMouseOver={(e) => (e.currentTarget.style.color = '#e0e0e0')}
            onMouseOut={(e) => (e.currentTarget.style.color = '#999')}
          >
            ×
          </button>
        </div>

        {/* Body */}
        <div style={{
          padding: isMobile ? '8px' : '16px',
          flex: 1,
          overflow: 'auto',
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
        }}>
          {error && (
            <div
              style={{
                backgroundColor: '#2a1a1a',
                border: '1px solid #ef5350',
                borderRadius: '4px',
                padding: isMobile ? '8px 12px' : '12px 16px',
                marginBottom: isMobile ? '8px' : '16px',
                display: 'flex',
                alignItems: 'center',
                gap: '8px',
              }}
            >
              <span style={{ color: '#ef5350' }}>⚠</span>
              <span style={{ color: '#e0e0e0', fontSize: isMobile ? '12px' : '14px' }}>{error}</span>
            </div>
          )}

          <div style={{ position: 'relative', height: isMobile ? '450px' : '680px', width: '100%' }}>
            {loading && (
              <div
                style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  backgroundColor: 'rgba(26, 26, 26, 0.7)',
                  zIndex: 10,
                  display: 'flex',
                  flexDirection: 'column',
                  alignItems: 'center',
                  justifyContent: 'center',
                  gap: '16px',
                }}
              >
                <div
                  style={{
                    width: '40px',
                    height: '40px',
                    border: '3px solid #404040',
                    borderTop: '3px solid #3182ce',
                    borderRadius: '50%',
                    animation: 'spin 1s linear infinite',
                  }}
                />
                <span style={{ color: '#e0e0e0' }}>加载K线数据...</span>
              </div>
            )}
            <div ref={chartRef} style={{ width: '100%', height: '100%' }} />
          </div>
        </div>
      </div>
      {/* 添加旋转动画的 CSS */}
      <style>{`
        @keyframes spin {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
      `}</style>
    </>
  );

  return createPortal(modalContent, portalContainer);
};

export default KLineChartModal;
