import React, { useEffect, useRef } from 'react';
import './style.less';

interface CustomBarLineChartProps {
  barData: number[];
  lineData: number[];
}

const CustomBarLineChart: React.FC<CustomBarLineChartProps> = ({ barData, lineData }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const labels = ['<5min', '5~10min', '10~15min', '15~30min', '30~60min'];
    const duration = 1000;
    const start = performance.now();
    const barWidthScale = 0.66;

    const draw = (timestamp: number) => {
      const progress = Math.min((timestamp - start) / duration, 1);

      const chartWidth = canvas.width;
      const chartHeight = canvas.height;
      const leftPadding = chartWidth * 0.1;
      const rightPadding = chartWidth * 0.1;
      const bottomPadding = chartHeight * 0.1;
      const topPadding = chartHeight * 0.1;

      const barWidth = ((chartWidth - leftPadding - rightPadding - (labels.length - 1) * (chartWidth * 0.05)) / labels.length) * barWidthScale;
      const barSpacing = chartWidth * 0.05;

      const maxBarHeight = chartHeight - topPadding - bottomPadding;
      const maxDataValue = Math.max(...barData, ...lineData) * 1.2;
      const lineOffset = chartHeight * 0.2;
      const barDepth = barWidth * 0.3;

      ctx.clearRect(0, 0, chartWidth, chartHeight);

      const yLabels = [0, 20, 40, 60, 80, 100];
      yLabels.forEach(value => {
        const y = chartHeight - bottomPadding - (value / 100) * maxBarHeight;

        ctx.strokeStyle = '#3e4b5b';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(leftPadding, y);
        ctx.lineTo(chartWidth - rightPadding, y);
        ctx.stroke();

        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'right';
        ctx.font = `${chartHeight * 0.03}px Arial`;
        ctx.fillText(`${value}%`, leftPadding - 10, y + 3);
      });

      barData.forEach((value, index) => {
        const barHeight = (value / maxDataValue) * maxBarHeight * progress;
        const x = leftPadding + index * (barWidth + barSpacing) + barSpacing;
        const y = chartHeight - bottomPadding - barHeight;

        ctx.fillStyle = '#4DB6E1';
        ctx.beginPath();
        ctx.moveTo(x, chartHeight - bottomPadding);
        ctx.lineTo(x + barWidth, chartHeight - bottomPadding);
        ctx.lineTo(x + barWidth, y);
        ctx.lineTo(x, y);
        ctx.closePath();
        ctx.fill();

        ctx.fillStyle = '#8ED6FF';
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x + barDepth, y - barDepth);
        ctx.lineTo(x + barWidth + barDepth, y - barDepth);
        ctx.lineTo(x + barWidth, y);
        ctx.closePath();
        ctx.fill();

        ctx.fillStyle = '#3A9AD9';
        ctx.beginPath();
        ctx.moveTo(x + barWidth, y);
        ctx.lineTo(x + barWidth + barDepth, y - barDepth);
        ctx.lineTo(x + barWidth + barDepth, chartHeight - bottomPadding - barHeight);
        ctx.lineTo(x + barWidth, chartHeight - bottomPadding);
        ctx.closePath();
        ctx.fill();

        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'center';
        ctx.font = `${chartHeight * 0.03}px Arial`;
        ctx.fillText(`${Math.round(value * progress)}%`, x + barWidth / 2, y - 10);
      });

      ctx.beginPath();
      ctx.strokeStyle = '#FFD700';
      ctx.lineWidth = 2;

      const controlPoint = (current: { x: number; y: number; }, previous: { x: number; y: number; }, next: { x: number; y: number; }, reverse: boolean) => {
        const smoothing = 0.2;
        const o = {
          length: Math.hypot(next.x - previous.x, next.y - previous.y),
          angle: Math.atan2(next.y - previous.y, next.x - previous.x)
        };
        const angle = reverse ? o.angle + Math.PI : o.angle;
        const length = o.length * smoothing;
        return {
          x: current.x + Math.cos(angle) * length,
          y: current.y + Math.sin(angle) * length
        };
      };

      const points = lineData.map((value, index) => ({
        x: leftPadding + index * (barWidth + barSpacing) + barSpacing + barWidth / 2,
        y: chartHeight - bottomPadding - (value / maxDataValue) * maxBarHeight * progress - lineOffset,
      }));

      const createPath = (points: { x: number; y: number; }[], ctx: CanvasRenderingContext2D) => {
        if (points.length === 0) return;
        ctx.moveTo(points[0].x, points[0].y);
        for (let i = 0; i < points.length - 1; i++) {
          const cp1 = controlPoint(points[i], points[i - 1] || points[i], points[i + 1], false);
          const cp2 = controlPoint(points[i + 1], points[i], points[i + 2] || points[i + 1], true);
          ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, points[i + 1].x, points[i + 1].y);
        }
      };

      createPath(points, ctx);
      ctx.stroke();

      lineData.forEach((value, index) => {
        const x = leftPadding + index * (barWidth + barSpacing) + barSpacing + barWidth / 2;
        const y = chartHeight - bottomPadding - (value / maxDataValue) * maxBarHeight * progress - lineOffset;

        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'center';
        ctx.font = `${chartHeight * 0.03}px Arial`;
        ctx.fillText(`${Math.round(value * progress)}%`, x, y - 10);
      });

      // 在每次绘制时始终绘制x轴标签
      labels.forEach((label, index) => {
        const x = leftPadding + index * (barWidth + barSpacing) + barSpacing;
        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'center';
        ctx.font = `${chartHeight * 0.03}px Arial`;
        ctx.fillText(label, x + barWidth / 2, chartHeight - bottomPadding + 20);
      });

      if (progress < 1) {
        requestAnimationFrame(draw);
      }
    };

    const resizeCanvas = () => {
      canvas.width = canvas.clientWidth;
      canvas.height = canvas.clientHeight;
      draw(performance.now());
    };

    resizeCanvas();

    window.addEventListener('resize', resizeCanvas);
    return () => window.removeEventListener('resize', resizeCanvas);
  }, [barData, lineData]);

  return <canvas ref={canvasRef} className="custom-chart" />;
};

export default CustomBarLineChart;
