/**
 * Live Chart Component
 *
 * Displays real-time data as a simple line chart.
 */

import React, { useMemo } from 'react';
import classNames from 'classnames';
import { useSocket } from '../../lib/realtime/useSocket';
import type { TransparencyEventType } from '../../lib/realtime/types';

interface LiveChartProps {
  eventTypes?: TransparencyEventType[];
  dataKey?: string;
  title?: string;
  color?: string;
  height?: number;
  maxDataPoints?: number;
  showGrid?: boolean;
  className?: string;
}

/**
 * Simple SVG line chart for real-time data
 */
export function LiveChart({
  eventTypes = ['system.metric'],
  dataKey = 'value',
  title = 'Live Data',
  color = '#3B82F6',
  height = 120,
  maxDataPoints = 30,
  showGrid = true,
  className,
}: LiveChartProps) {
  const { events } = useSocket({
    eventTypes,
    maxEvents: maxDataPoints,
  });

  // Extract data points
  const dataPoints = useMemo(() => {
    return events
      .filter((e) => e.data && typeof e.data[dataKey] === 'number')
      .map((e) => ({
        value: e.data[dataKey] as number,
        timestamp: new Date(e.timestamp).getTime(),
      }))
      .reverse()
      .slice(-maxDataPoints);
  }, [events, dataKey, maxDataPoints]);

  // Calculate chart dimensions
  const chartWidth = 400;
  const chartHeight = height - 40;
  const padding = { top: 10, right: 10, bottom: 20, left: 40 };
  const innerWidth = chartWidth - padding.left - padding.right;
  const innerHeight = chartHeight - padding.top - padding.bottom;

  // Calculate scales
  const { minValue, maxValue, points, pathD } = useMemo(() => {
    if (dataPoints.length === 0) {
      return { minValue: 0, maxValue: 100, points: [], pathD: '' };
    }

    const values = dataPoints.map((d) => d.value);
    const min = Math.min(...values);
    const max = Math.max(...values);
    const range = max - min || 1;

    const pts = dataPoints.map((d, i) => ({
      x: padding.left + (i / Math.max(1, dataPoints.length - 1)) * innerWidth,
      y: padding.top + innerHeight - ((d.value - min) / range) * innerHeight,
    }));

    const d = pts.length > 0
      ? `M ${pts.map((p) => `${p.x},${p.y}`).join(' L ')}`
      : '';

    return { minValue: min, maxValue: max, points: pts, pathD: d };
  }, [dataPoints, innerWidth, innerHeight, padding]);

  // Latest value
  const latestValue = dataPoints.length > 0 ? dataPoints[dataPoints.length - 1].value : null;

  return (
    <div className={classNames('bg-white rounded-lg p-4 border border-gray-200', className)}>
      {/* Header */}
      <div className="flex items-center justify-between mb-2">
        <h4 className="text-sm font-medium text-gray-700">{title}</h4>
        {latestValue !== null && (
          <span className="text-lg font-bold" style={{ color }}>
            {latestValue.toFixed(1)}
          </span>
        )}
      </div>

      {/* Chart */}
      <svg
        width="100%"
        height={chartHeight}
        viewBox={`0 0 ${chartWidth} ${chartHeight}`}
        preserveAspectRatio="xMidYMid meet"
      >
        {/* Grid */}
        {showGrid && (
          <g className="text-gray-200">
            {/* Horizontal grid lines */}
            {[0, 0.25, 0.5, 0.75, 1].map((ratio) => (
              <line
                key={`h-${ratio}`}
                x1={padding.left}
                y1={padding.top + innerHeight * ratio}
                x2={padding.left + innerWidth}
                y2={padding.top + innerHeight * ratio}
                stroke="currentColor"
                strokeDasharray="2,2"
              />
            ))}
            {/* Vertical grid lines */}
            {[0, 0.5, 1].map((ratio) => (
              <line
                key={`v-${ratio}`}
                x1={padding.left + innerWidth * ratio}
                y1={padding.top}
                x2={padding.left + innerWidth * ratio}
                y2={padding.top + innerHeight}
                stroke="currentColor"
                strokeDasharray="2,2"
              />
            ))}
          </g>
        )}

        {/* Y-axis labels */}
        <g className="text-gray-500 text-xs">
          <text x={padding.left - 5} y={padding.top + 4} textAnchor="end">
            {maxValue.toFixed(0)}
          </text>
          <text x={padding.left - 5} y={padding.top + innerHeight} textAnchor="end">
            {minValue.toFixed(0)}
          </text>
        </g>

        {/* Line path */}
        {pathD && (
          <>
            {/* Gradient area */}
            <defs>
              <linearGradient id="areaGradient" x1="0" x2="0" y1="0" y2="1">
                <stop offset="0%" stopColor={color} stopOpacity={0.2} />
                <stop offset="100%" stopColor={color} stopOpacity={0} />
              </linearGradient>
            </defs>
            <path
              d={`${pathD} L ${points[points.length - 1]?.x},${padding.top + innerHeight} L ${points[0]?.x},${padding.top + innerHeight} Z`}
              fill="url(#areaGradient)"
            />
            <path
              d={pathD}
              fill="none"
              stroke={color}
              strokeWidth={2}
              strokeLinecap="round"
              strokeLinejoin="round"
            />
          </>
        )}

        {/* Data points */}
        {points.map((p, i) => (
          <circle
            key={i}
            cx={p.x}
            cy={p.y}
            r={i === points.length - 1 ? 4 : 2}
            fill={color}
          />
        ))}

        {/* No data message */}
        {dataPoints.length === 0 && (
          <text
            x={chartWidth / 2}
            y={chartHeight / 2}
            textAnchor="middle"
            className="text-gray-400 text-sm"
          >
            Waiting for data...
          </text>
        )}
      </svg>
    </div>
  );
}

/**
 * Event count chart - shows event frequency over time
 */
export function EventCountChart({
  className,
}: {
  className?: string;
}) {
  const { events } = useSocket({ maxEvents: 100 });

  // Group events by minute
  const countsByMinute = useMemo(() => {
    const counts: Record<string, number> = {};
    const now = Date.now();

    // Initialize last 10 minutes
    for (let i = 0; i < 10; i++) {
      const minute = Math.floor((now - i * 60000) / 60000);
      counts[minute] = 0;
    }

    // Count events
    events.forEach((e) => {
      const minute = Math.floor(new Date(e.timestamp).getTime() / 60000);
      if (counts[minute] !== undefined) {
        counts[minute]++;
      }
    });

    return Object.entries(counts)
      .sort(([a], [b]) => Number(a) - Number(b))
      .map(([, count]) => count);
  }, [events]);

  const maxCount = Math.max(...countsByMinute, 1);

  return (
    <div className={classNames('bg-white rounded-lg p-4 border border-gray-200', className)}>
      <h4 className="text-sm font-medium text-gray-700 mb-2">Events per Minute</h4>

      <div className="flex items-end gap-1 h-16">
        {countsByMinute.map((count, i) => (
          <div
            key={i}
            className="flex-1 bg-blue-500 rounded-t transition-all duration-300"
            style={{ height: `${(count / maxCount) * 100}%` }}
            title={`${count} events`}
          />
        ))}
      </div>

      <div className="flex justify-between text-xs text-gray-400 mt-1">
        <span>10m ago</span>
        <span>Now</span>
      </div>
    </div>
  );
}

export default LiveChart;
