import React, { lazy, Suspense, useEffect, useMemo, useState } from 'react';
import { XCard, registerCatalog, type XAgentCommand_v0_9 } from '@ant-design/x-card';
import { Button, Spin, Tag, Tooltip, Typography } from 'antd';
import { DownloadOutlined } from '@ant-design/icons';
import type { EChartsType } from 'echarts/core';
import type { EChartsOption } from '../../components/ECharts';
import type { AiChartSchema } from './types';
import { useXCardSurface } from './useSubmissionState';

// echarts 体积较大，仅在真正渲染图表时加载，避免打开 AI 抽屉就拉取
const ReactECharts = lazy(() => import('../../components/ECharts'));

const CHART_CATALOG_ID = 'gongxue-chart-catalog';

registerCatalog({
  catalogId: CHART_CATALOG_ID,
  components: {
    ChartPreview: {
      type: 'object',
      properties: {
        chart: { type: 'object' },
      },
    },
  },
});

function surfaceId(chartId: string): string {
  return `chart-${chartId}`;
}

function numberValue(value: unknown): number {
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : 0;
}

const CHART_TYPE_LABELS: Record<string, string> = {
  line: '折线图',
  bar: '柱状图',
  pie: '饼图',
  area: '面积图',
  scatter: '散点图',
  radar: '雷达图',
  gauge: '仪表盘',
  funnel: '漏斗图',
};

function buildNameValueRows(chart: AiChartSchema): { name: string; value: number }[] {
  const nameField = chart.columns[0]?.key ?? '';
  const valueField = chart.columns[1]?.key ?? '';
  return chart.rows.map((row) => ({
    name: String(row[nameField] ?? ''),
    value: numberValue(row[valueField]),
  }));
}

function buildScatterOption(chart: AiChartSchema): EChartsOption {
  const columns = chart.columns;
  const nameField = columns[0]?.key ?? '';
  const xField = columns[1]?.key ?? '';
  const yField = columns[2]?.key ?? '';
  const data = chart.rows.map((row) => ({
    name: String(row[nameField] ?? ''),
    value: [numberValue(row[xField]), numberValue(row[yField])],
  }));
  return {
    tooltip: {
      trigger: 'item',
      formatter: (params: unknown) => {
        const item = params as { name?: string; value?: number[] };
        const [x, y] = item.value ?? [];
        return `${item.name ?? ''}: (${x ?? 0}, ${y ?? 0})`;
      },
    },
    grid: { left: 8, right: 16, top: 32, bottom: 48, containLabel: true },
    xAxis: { type: 'value', name: columns[1]?.title },
    yAxis: { type: 'value', name: columns[2]?.title },
    series: [{ type: 'scatter', symbolSize: 10, data }],
  };
}

function buildRadarOption(chart: AiChartSchema): EChartsOption {
  const columns = chart.columns;
  const seriesNameField = columns[0]?.key ?? '';
  const indicatorColumns = columns.slice(1);
  const indicators = indicatorColumns.map((column) => {
    const values = chart.rows.map((row) => numberValue(row[column.key]));
    const max = Math.max(1, ...values);
    return { name: column.title, max: Math.ceil(max * 1.1) };
  });
  const seriesData = chart.rows.map((row) => ({
    name: String(row[seriesNameField] ?? ''),
    value: indicatorColumns.map((column) => numberValue(row[column.key])),
  }));
  return {
    tooltip: { trigger: 'item' },
    legend: { bottom: 0, type: 'scroll' },
    radar: { indicator: indicators, radius: '65%' },
    series: [{ type: 'radar', data: seriesData }],
  };
}

function buildGaugeOption(chart: AiChartSchema): EChartsOption {
  const columns = chart.columns;
  const nameField = columns[0]?.key ?? '';
  const valueField = columns[1]?.key ?? '';
  const maxField = columns[2]?.key;
  const gauges = chart.rows.map((row) => ({
    name: String(row[nameField] ?? ''),
    value: numberValue(row[valueField]),
    max: maxField ? Math.max(1, numberValue(row[maxField])) : 100,
  }));
  return {
    series: gauges.map((gauge, index) => ({
      type: 'gauge',
      center: [`${((index + 0.5) * 100) / gauges.length}%`, '58%'],
      radius: '75%',
      min: 0,
      max: gauge.max,
      title: { show: true, offsetCenter: [0, '82%'], fontSize: 12 },
      detail: { formatter: '{value}', fontSize: 14, offsetCenter: [0, '20%'] },
      data: [{ value: gauge.value, name: gauge.name }],
    })),
  };
}

function buildNameValueOption(chart: AiChartSchema): EChartsOption {
  const data = buildNameValueRows(chart);
  return chart.chartType === 'funnel'
    ? {
        tooltip: { trigger: 'item', formatter: '{b}: {c}' },
        legend: { bottom: 0, type: 'scroll' },
        series: [
          {
            type: 'funnel',
            left: '10%',
            top: 20,
            bottom: 40,
            width: '80%',
            minSize: '20%',
            label: { formatter: '{b}: {c}' },
            data,
          },
        ],
      }
    : {
        tooltip: { trigger: 'item' },
        legend: { bottom: 0, type: 'scroll' },
        series: [
          {
            type: 'pie',
            radius: ['35%', '68%'],
            center: ['50%', '45%'],
            data,
            label: { formatter: '{b}: {c}' },
          },
        ],
      };
}

function buildOption(chart: AiChartSchema): EChartsOption {
  if (chart.chartType === 'scatter') return buildScatterOption(chart);
  if (chart.chartType === 'radar') return buildRadarOption(chart);
  if (chart.chartType === 'gauge') return buildGaugeOption(chart);
  if (chart.chartType === 'funnel' || chart.chartType === 'pie') return buildNameValueOption(chart);
  return buildCategoryOption(chart);
}

function buildCategoryOption(chart: AiChartSchema): EChartsOption {
  const columns = chart.columns;
  const categoryField = columns[0]?.key ?? '';
  const categories = chart.rows.map((row) => String(row[categoryField] ?? ''));
  const series = columns.slice(1).map((column) => ({
    name: column.title,
    type: chart.chartType === 'area' ? 'line' : chart.chartType,
    smooth: chart.chartType === 'line',
    ...(chart.chartType === 'area' ? { areaStyle: { opacity: 0.18 } } : {}),
    data: chart.rows.map((row) => numberValue(row[column.key])),
  }));
  return {
    tooltip: { trigger: 'axis' },
    legend: { bottom: 0, type: 'scroll' },
    grid: { left: 8, right: 16, top: 32, bottom: 48, containLabel: true },
    xAxis: {
      type: 'category',
      data: categories,
      axisLabel: { interval: 0, rotate: categories.length > 8 ? 30 : 0 },
    },
    yAxis: { type: 'value' },
    series,
  };
}

interface ChartPreviewProps {
  chart?: AiChartSchema;
}

/**
 * A2UI component registered for the `gongxue-chart-catalog` catalog.
 * Receives the validated tabular chart data through data binding and
 * renders an ECharts option built from it.
 */
const ChartPreview: React.FC<ChartPreviewProps> = ({ chart }) => {
  const option = useMemo<EChartsOption>(() => (chart ? buildOption(chart) : {}), [chart]);
  const [instance, setInstance] = useState<EChartsType | null>(null);
  if (!chart) return null;
  // 空数据集：渲染明确占位，而不是一张空白图
  if (!chart.rows || chart.rows.length === 0) {
    return (
      <div className="ai-chat-chart-card">
        <div className="ai-chat-chart-card__header">
          <Typography.Text strong>{chart.title}</Typography.Text>
          <Tag color="blue">{CHART_TYPE_LABELS[chart.chartType] ?? chart.chartType}</Tag>
        </div>
        <div
          style={{
            height: 120,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}
        >
          <Typography.Text type="secondary">暂无数据</Typography.Text>
        </div>
      </div>
    );
  }

  const downloadImage = () => {
    if (!instance) return;
    const url = instance.getDataURL({
      type: 'png',
      pixelRatio: 2,
      backgroundColor: '#fff',
    });
    const link = document.createElement('a');
    link.href = url;
    link.download = `${chart.title || '图表'}.png`;
    document.body.appendChild(link);
    link.click();
    link.remove();
  };

  return (
    <div className="ai-chat-chart-card">
      <div className="ai-chat-chart-card__header">
        <Typography.Text strong>{chart.title}</Typography.Text>
        <span className="ai-chat-chart-card__header-actions">
          <Tag color="blue">{CHART_TYPE_LABELS[chart.chartType] ?? chart.chartType}</Tag>
          <Tooltip title="下载图片">
            <Button
              type="text"
              size="small"
              className="ai-chat-chart-card__download"
              aria-label="下载图表图片"
              icon={<DownloadOutlined />}
              onClick={downloadImage}
              disabled={!instance}
            />
          </Tooltip>
        </span>
      </div>
      <Suspense fallback={<Spin size="small" />}>
        <ReactECharts option={option} style={{ width: '100%', height: 260 }} onReady={setInstance} />
      </Suspense>
    </div>
  );
};

export interface DynamicChartProps {
  chart: AiChartSchema;
}

/**
 * Chart card rendered through the official @ant-design/x-card renderer.
 * Display-only: no submit endpoint, the schema lives in message metadata
 * so history replays identically.
 */
export const DynamicChart: React.FC<DynamicChartProps> = ({ chart }) => {
  const sid = surfaceId(chart.id);
  const { commands, pushCommands } = useXCardSurface(sid);

  useEffect(() => {
    const cmds: XAgentCommand_v0_9[] = [
      {
        version: 'v0.9',
        createSurface: { surfaceId: sid, catalogId: CHART_CATALOG_ID },
      },
      {
        version: 'v0.9',
        updateDataModel: {
          surfaceId: sid,
          path: '/chart',
          value: chart,
        },
      },
      {
        version: 'v0.9',
        updateComponents: {
          surfaceId: sid,
          components: [
            {
              id: 'root',
              component: 'ChartPreview',
              chart: { path: '/chart' },
            },
          ],
        },
      },
    ];
    pushCommands(cmds);
  }, [chart, pushCommands, sid]);

  return (
    <div className="ai-chat-chart">
      <XCard.Box components={{ ChartPreview }} commands={commands}>
        <XCard.Card id={surfaceId(chart.id)} />
      </XCard.Box>
    </div>
  );
};
