import * as React from 'react';
import * as echarts from 'echarts';
import './style.scss';

/**
 * 图表组件属性接口
 * 定义了图表组件接收的所有配置参数
 */
interface ChartWidgetProps {
  /** 图表类型：line(折线图)、bar(柱状图)、pie(饼图)、scatter(散点图)、radar(雷达图)、gauge(仪表盘)、funnel(漏斗图)、sankey(桑基图) */
  chartType: string;
  /** 图表主标题 */
  title: string;
  /** 图表副标题 */
  subtitle: string;
  /** 图表宽度(像素) */
  width: number;
  /** 图表高度(像素) */
  height: number;
  /** 图表主题：default(默认)、dark(深色)、light(明亮)、business(商务) */
  theme: string;
  /** 是否显示图例 */
  showLegend: boolean;
  /** 是否显示提示框 */
  showTooltip: boolean;
  /** 是否显示数据缩放控件 */
  showDataZoom: boolean;
  /** 是否显示网格线 */
  showGrid: boolean;
  /** 背景颜色 */
  backgroundColor: string;
  /** 文字颜色 */
  textColor: string;
  /** 模拟数据对象，包含各种图表类型的数据 */
  mockData: any;
  /** 数据配置对象 */
  dataConfig: any;
  /** AMIS 数据对象，包含用户信息和系统信息 */
  data?: any;
}

/**
 * 酷炫图表组件
 * 基于 ECharts 实现的多类型图表组件，支持折线图、柱状图、饼图、散点图、雷达图、仪表盘、漏斗图、桑基图
 * 提供丰富的配置选项和交互功能
 */
export default class ChartWidget extends React.PureComponent<ChartWidgetProps> {
  /** 图表容器的 DOM 引用 */
  private chartRef: React.RefObject<HTMLDivElement>;

  /** ECharts 实例对象 */
  private chartInstance: echarts.ECharts | null = null;

  constructor(props: ChartWidgetProps) {
    super(props);
    this.chartRef = React.createRef();
  }

  /**
   * 组件默认属性配置
   * 当父组件未传入对应属性时使用这些默认值
   */
  static defaultProps = {
    chartType: 'line',
    title: '图表标题',
    subtitle: '',
    width: 800,
    height: 400,
    theme: 'default',
    showLegend: true,
    showTooltip: true,
    showDataZoom: false,
    showGrid: true,
    backgroundColor: 'transparent',
    textColor: '#333',
    mockData: {},
    dataConfig: {},
  };

  /**
   * 组件挂载完成后初始化图表
   */
  componentDidMount() {
    this.initChart();
  }

  /**
   * 组件更新时检查是否需要重新渲染图表
   * @param prevProps 上一次的属性
   */
  componentDidUpdate(prevProps: ChartWidgetProps) {
    if (this.shouldUpdateChart(prevProps)) {
      this.updateChart();
    }
  }

  /**
   * 组件卸载前清理图表实例，防止内存泄漏
   */
  componentWillUnmount() {
    if (this.chartInstance) {
      this.chartInstance.dispose();
    }
  }

  /**
   * 判断是否需要更新图表
   * 通过比较当前属性和上一次属性，决定是否重新渲染图表
   * @param prevProps 上一次的属性
   * @returns 是否需要更新图表
   */
  shouldUpdateChart(prevProps: ChartWidgetProps) {
    const {
      chartType,
      mockData,
      dataConfig,
      width,
      height,
      theme,
      title,
      subtitle,
      backgroundColor,
      textColor,
      showLegend,
      showTooltip,
      showDataZoom,
      showGrid,
    } = this.props;
    return (
      chartType !== prevProps.chartType ||
      mockData !== prevProps.mockData ||
      dataConfig !== prevProps.dataConfig ||
      title !== prevProps.title ||
      subtitle !== prevProps.subtitle ||
      width !== prevProps.width ||
      height !== prevProps.height ||
      theme !== prevProps.theme ||
      backgroundColor !== prevProps.backgroundColor ||
      textColor !== prevProps.textColor ||
      showLegend !== prevProps.showLegend ||
      showTooltip !== prevProps.showTooltip ||
      showDataZoom !== prevProps.showDataZoom ||
      showGrid !== prevProps.showGrid
    );
  }

  /**
   * 初始化图表实例
   * 创建 ECharts 实例并设置初始配置
   */
  initChart() {
    if (!this.chartRef.current) return;

    this.chartInstance = echarts.init(this.chartRef.current, this.props.theme);
    this.updateChart();
  }

  /**
   * 更新图表配置
   * 根据当前属性生成新的图表配置并应用
   */
  updateChart() {
    if (!this.chartInstance) return;

    try {
      const option = this.getChartOption();
      // 验证 option 是否有效
      if (option && option.series && Array.isArray(option.series)) {
        this.chartInstance.setOption(option, true);
      } else {
        console.warn('Chart option is invalid:', option);
      }
    } catch (error) {
      console.error('Error updating chart:', error);
    }
  }

  /**
   * 获取图表配置选项
   * 根据组件属性生成 ECharts 配置对象
   * @returns ECharts 配置对象
   */
  getChartOption() {
    const {
      chartType,
      title,
      subtitle,
      showLegend,
      showTooltip,
      showDataZoom,
      showGrid,
      backgroundColor,
      textColor,
      mockData,
      dataConfig,
    } = this.props;

    // 基础配置选项，所有图表类型共享
    const baseOption = {
      backgroundColor: backgroundColor || 'transparent',
      textStyle: {
        color: textColor || '#333',
      },
      title: {
        text: title || '图表标题',
        subtext: subtitle || '',
        left: 'left',
        textStyle: {
          color: textColor || '#333',
          fontSize: 18,
          fontWeight: 'bold',
        },
        subtextStyle: {
          color: textColor || '#666',
          fontSize: 12,
        },
      },
      tooltip: showTooltip
        ? {
            trigger: 'axis',
            backgroundColor: 'rgba(0, 0, 0, 0.8)',
            borderColor: '#333',
            textStyle: {
              color: '#fff',
            },
            axisPointer: {
              type: 'cross',
              crossStyle: {
                color: '#999',
              },
            },
          }
        : undefined,
      legend: showLegend
        ? {
            data: mockData?.series?.map((s: any) => s.name) || [],
            top: 'bottom',
            textStyle: {
              color: textColor || '#333',
            },
          }
        : undefined,
      grid: showGrid
        ? {
            left: '3%',
            right: '4%',
            bottom: '10%',
            top: '18%',
            containLabel: true,
          }
        : undefined,
      dataZoom: showDataZoom
        ? [
            {
              type: 'inside',
              start: 0,
              end: 100,
            },
            {
              start: 0,
              end: 100,
              height: 30,
              bottom: 10,
            },
          ]
        : undefined,
    };

    // 根据图表类型返回对应的配置
    switch (chartType) {
      case 'line':
        return this.getLineChartOption(baseOption, mockData, dataConfig);
      case 'bar':
        return this.getBarChartOption(baseOption, mockData, dataConfig);
      case 'pie':
        return this.getPieChartOption(baseOption, mockData, dataConfig);
      case 'scatter':
        return this.getScatterChartOption(baseOption, mockData, dataConfig);
      case 'radar':
        return this.getRadarChartOption(baseOption, mockData, dataConfig);
      case 'gauge':
        return this.getGaugeChartOption(baseOption, mockData, dataConfig);
      case 'funnel':
        return this.getFunnelChartOption(baseOption, mockData, dataConfig);
      case 'sankey':
        return this.getSankeyChartOption(baseOption, mockData, dataConfig);
      default:
        return this.getLineChartOption(baseOption, mockData, dataConfig);
    }
  }

  /**
   * 获取折线图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 折线图配置对象
   */
  getLineChartOption(baseOption: any, mockData: any, dataConfig: any) {
    const series = mockData?.series || [
      {
        name: '数据',
        data: [120, 200, 150, 80, 70, 110, 130],
      },
    ];

    // 确保每个 series 都有正确的 type 属性
    const formattedSeries = series.map((item: any) => ({
      name: item.name || '数据',
      type: 'line',
      data: item.data || [],
      smooth: true,
      symbol: 'circle',
      symbolSize: 6,
      lineStyle: {
        width: 3,
      },
      areaStyle: {
        opacity: 0.3,
      },
    }));

    return {
      ...baseOption,
      xAxis: {
        type: 'category',
        data: mockData?.xAxis || [
          'Mon',
          'Tue',
          'Wed',
          'Thu',
          'Fri',
          'Sat',
          'Sun',
        ],
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      yAxis: {
        type: 'value',
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      series: formattedSeries,
    };
  }

  /**
   * 获取柱状图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 柱状图配置对象
   */
  getBarChartOption(baseOption: any, mockData: any, dataConfig: any) {
    const series = mockData?.series || [
      {
        name: '数据',
        data: [120, 200, 150, 80, 70, 110, 130],
      },
    ];

    // 确保每个 series 都有正确的 type 属性
    const formattedSeries = series.map((item: any) => ({
      name: item.name || '数据',
      type: 'bar',
      data: item.data || [],
      itemStyle: {
        borderRadius: [4, 4, 0, 0],
      },
    }));

    return {
      ...baseOption,
      xAxis: {
        type: 'category',
        data: mockData?.xAxis || [
          'Mon',
          'Tue',
          'Wed',
          'Thu',
          'Fri',
          'Sat',
          'Sun',
        ],
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      yAxis: {
        type: 'value',
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      series: formattedSeries,
    };
  }

  /**
   * 获取饼图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 饼图配置对象
   */
  getPieChartOption(baseOption: any, mockData: any, dataConfig: any) {
    // 饼图数据获取逻辑修复
    let pieData = [];
    
    // 尝试多种数据源
    if (mockData?.pieData && Array.isArray(mockData.pieData)) {
      // 优先使用专门的饼图数据
      pieData = mockData.pieData;
    } else if (mockData?.series?.[0]?.data && Array.isArray(mockData.series[0].data)) {
      // 使用系列数据
      pieData = mockData.series[0].data;
    } else if (mockData?.series && Array.isArray(mockData.series)) {
      // 将系列数据转换为饼图格式
      pieData = mockData.series.map((item: any) => ({
        name: item.name || '数据',
        value: Array.isArray(item.data) ? item.data.reduce((sum: number, val: number) => sum + val, 0) : item.value || 0
      }));
    } else {
      // 使用默认数据
      pieData = [
        { value: 1048, name: '搜索引擎' },
        { value: 735, name: '直接访问' },
        { value: 580, name: '邮件营销' },
        { value: 484, name: '联盟广告' },
        { value: 300, name: '视频广告' },
      ];
    }

    return {
      ...baseOption,
      series: [
        {
          name: '数据',
          type: 'pie',
          radius: ['40%', '70%'],
          center: ['50%', '50%'],
          data: pieData,
          label: {
            show: true,
            position: 'outside',
            fontSize: 12,
            color: this.props.textColor || '#333',
            formatter: '{c} ({d}%)',
            overflow: 'truncate'
          },
          labelLine: {
            show: true,
            length: 15,
            length2: 10,
            smooth: true,
            lineStyle: {
              color: this.props.textColor || '#333',
              width: 1
            }
          },
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
            label: {
              show: true,
              fontSize: 14,
              fontWeight: 'bold'
            }
          },
        },
      ],
    };
  }

  /**
   * 获取散点图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 散点图配置对象
   */
  getScatterChartOption(baseOption: any, mockData: any, dataConfig: any) {
    return {
      ...baseOption,
      xAxis: {
        type: 'value',
        scale: true,
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      yAxis: {
        type: 'value',
        scale: true,
        axisLine: {
          lineStyle: {
            color: this.props.textColor || '#333',
          },
        },
      },
      series: [
        {
          name: '数据',
          type: 'scatter',
          data: mockData?.series?.[0]?.data || [
            [161.2, 51.6],
            [167.5, 59.0],
            [159.5, 49.2],
            [157.0, 63.0],
            [155.8, 53.6],
            [170.0, 59.0],
            [159.1, 47.6],
            [166.0, 69.8],
            [176.2, 66.8],
            [160.2, 75.2],
          ],
          symbolSize: 8,
        },
      ],
    };
  }

  /**
   * 获取雷达图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 雷达图配置对象
   */
  getRadarChartOption(baseOption: any, mockData: any, dataConfig: any) {
    return {
      ...baseOption,
      radar: {
        indicator: mockData?.indicator || [
          { name: '销售', max: 6500 },
          { name: '管理', max: 16000 },
          { name: '信息技术', max: 30000 },
          { name: '客服', max: 38000 },
          { name: '研发', max: 52000 },
          { name: '市场', max: 25000 },
        ],
      },
      series: [
        {
          name: '数据',
          type: 'radar',
          data: mockData?.series || [
            {
              value: [4200, 3000, 20000, 35000, 50000, 18000],
              name: '预算分配',
            },
          ],
        },
      ],
    };
  }

  /**
   * 获取仪表盘配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 仪表盘配置对象
   */
  getGaugeChartOption(baseOption: any, mockData: any, dataConfig: any) {
    return {
      ...baseOption,
      series: [
        {
          name: '数据',
          type: 'gauge',
          data: mockData?.series?.[0]?.data || [{ value: 50, name: '完成率' }],
          detail: {
            formatter: '{value}%',
          },
        },
      ],
    };
  }

  /**
   * 获取漏斗图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 漏斗图配置对象
   */
  getFunnelChartOption(baseOption: any, mockData: any, dataConfig: any) {
    return {
      ...baseOption,
      series: [
        {
          name: '数据',
          type: 'funnel',
          left: '10%',
          top: 60,
          bottom: 60,
          width: '80%',
          min: 0,
          max: 100,
          minSize: '0%',
          maxSize: '100%',
          sort: 'descending',
          gap: 2,
          label: {
            show: true,
            position: 'inside',
          },
          labelLine: {
            length: 10,
            lineStyle: {
              width: 1,
              type: 'solid',
            },
          },
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 1,
          },
          emphasis: {
            label: {
              fontSize: 20,
            },
          },
          data: mockData?.series?.[0]?.data || [
            { value: 60, name: '访问' },
            { value: 40, name: '咨询' },
            { value: 20, name: '订单' },
            { value: 80, name: '点击' },
            { value: 100, name: '展现' },
          ],
        },
      ],
    };
  }

  /**
   * 获取桑基图配置
   * @param baseOption 基础配置选项
   * @param mockData 模拟数据
   * @param dataConfig 数据配置
   * @returns 桑基图配置对象
   */
  getSankeyChartOption(baseOption: any, mockData: any, dataConfig: any) {
    return {
      ...baseOption,
      series: [
        {
          name: '数据',
          type: 'sankey',
          data: mockData?.nodes || [
            { name: '节点1' },
            { name: '节点2' },
            { name: '节点3' },
            { name: '节点4' },
          ],
          links: mockData?.links || [
            { source: '节点1', target: '节点2', value: 10 },
            { source: '节点2', target: '节点3', value: 15 },
            { source: '节点3', target: '节点4', value: 20 },
          ],
          emphasis: {
            focus: 'adjacency',
          },
          lineStyle: {
            color: 'gradient',
            curveness: 0.5,
          },
        },
      ],
    };
  }

  /**
   * 渲染组件
   * 显示用户信息（如果可用）和图表容器
   * @returns JSX 元素
   */
  render() {
    const { width, height } = this.props;
    const curAmisData = this.props.data || {};
    const userInfo = curAmisData.__AmisCurrentUser;
    const systemInfo = curAmisData.__AmisSystemInfo || {};

    return (
      <div className="chart-widget-container">
        {/* 显示当前用户信息 */}
        {userInfo && userInfo.name && (
          <div className="user-info">
            <span className="user-name">用户：{userInfo.name}</span>
            {systemInfo.tenantName && (
              <span className="tenant-name">租户：{systemInfo.tenantName}</span>
            )}
          </div>
        )}
        {/* 图表容器 */}
        <div
          ref={this.chartRef}
          className="chart-container"
          style={{
            width: width || '100%',
            height: height || 400,
          }}
        />
      </div>
    );
  }
}
