import React, { useState, useRef, useEffect, useMemo } from 'react';
import { Card, Button, Badge, Select, Modal } from '../../ui';
import type { 
  ChartWidget as ChartWidgetType, 
  ChartSeries, 
  ChartConfig, 
  ChartFilter, 
  ExportFormat,
  ChartType 
} from './types';

interface ChartWidgetProps {
  widget: ChartWidgetType;
  data?: ChartSeries[];
  loading?: boolean;
  error?: string;
  onConfigChange?: (config: Partial<ChartConfig>) => void;
  onFiltersChange?: (filters: ChartFilter[]) => void;
  onRefresh?: () => void;
  onExport?: (format: ExportFormat) => void;
  onFullscreen?: () => void;
  interactive?: boolean;
  showControls?: boolean;
  showTitle?: boolean;
  showSubtitle?: boolean;
  className?: string;
}

interface ChartPoint {
  x: number;
  y: number;
  label: string;
}

const CHART_TYPE_LABELS: Record<ChartType, string> = {
  line: 'Líneas',
  bar: 'Barras',
  pie: 'Circular',
  area: 'Área',
  scatter: 'Dispersión',
  doughnut: 'Dona',
  radar: 'Radar',
  mixed: 'Mixto',
};

const EXPORT_FORMATS: ExportFormat[] = ['png', 'svg', 'pdf', 'csv', 'excel'];

export const ChartWidget: React.FC<ChartWidgetProps> = ({
  widget,
  data = [],
  loading = false,
  error,
  onConfigChange,
  onFiltersChange,
  onRefresh,
  onExport,
  onFullscreen,
  interactive = true,
  showControls = true,
  showTitle = true,
  showSubtitle = true,
  className = '',
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isConfigModalOpen, setIsConfigModalOpen] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [hoveredPoint, setHoveredPoint] = useState<{ seriesIndex: number; pointIndex: number } | null>(null);
  const [selectedExportFormat, setSelectedExportFormat] = useState<ExportFormat>('png');

  const chartDimensions = useMemo(() => ({
    width: widget.dimensions?.width || '100%',
    height: widget.dimensions?.height || 400,
    aspectRatio: widget.dimensions?.aspect_ratio || '16:9',
  }), [widget.dimensions]);

  // Simple chart rendering logic
  useEffect(() => {
    if (!canvasRef.current || !data.length || loading) return;

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

    // Set canvas size
    const rect = canvas.getBoundingClientRect();
    canvas.width = rect.width;
    canvas.height = rect.height;

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Draw based on chart type
    switch (widget.type) {
      case 'bar':
        drawBarChart(ctx, canvas, data);
        break;
      case 'line':
        drawLineChart(ctx, canvas, data);
        break;
      case 'pie':
        drawPieChart(ctx, canvas, data);
        break;
      case 'area':
        drawAreaChart(ctx, canvas, data);
        break;
      default:
        drawBarChart(ctx, canvas, data);
    }
  }, [data, widget.type, loading]);

  const drawBarChart = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, chartData: ChartSeries[]) => {
    if (!chartData.length) return;

    const padding = 60;
    const chartWidth = canvas.width - 2 * padding;
    const chartHeight = canvas.height - 2 * padding;
    
    // Get all data points
    const allPoints = chartData.flatMap(series => series.data);
    const maxY = Math.max(...allPoints.map(point => point.y));
    const minY = Math.min(...allPoints.map(point => point.y));
    
    const firstSeries = chartData[0];
    const barWidth = chartWidth / firstSeries.data.length / chartData.length;
    const barSpacing = barWidth * 0.1;

    // Draw grid
    ctx.strokeStyle = '#e5e7eb';
    ctx.lineWidth = 1;
    for (let i = 0; i <= 5; i++) {
      const y = padding + (chartHeight * i) / 5;
      ctx.beginPath();
      ctx.moveTo(padding, y);
      ctx.lineTo(padding + chartWidth, y);
      ctx.stroke();
    }

    // Draw bars
    chartData.forEach((series, seriesIndex) => {
      const color = series.color || widget.config.color_scheme[seriesIndex % widget.config.color_scheme.length];
      ctx.fillStyle = color;

      series.data.forEach((point, pointIndex) => {
        const x = padding + (pointIndex * chartWidth) / firstSeries.data.length + (seriesIndex * barWidth);
        const barHeight = ((point.y - minY) / (maxY - minY)) * chartHeight;
        const y = padding + chartHeight - barHeight;

        ctx.fillRect(x + barSpacing, y, barWidth - barSpacing, barHeight);

        // Add value labels if enabled
        if (widget.config.show_tooltips) {
          ctx.fillStyle = '#374151';
          ctx.font = '12px sans-serif';
          ctx.textAlign = 'center';
          ctx.fillText(point.y.toString(), x + barWidth / 2, y - 5);
          ctx.fillStyle = color;
        }
      });
    });

    // Draw axes
    ctx.strokeStyle = '#374151';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(padding, padding);
    ctx.lineTo(padding, padding + chartHeight);
    ctx.lineTo(padding + chartWidth, padding + chartHeight);
    ctx.stroke();

    // Draw labels
    ctx.fillStyle = '#6b7280';
    ctx.font = '12px sans-serif';
    ctx.textAlign = 'center';
    
    // X-axis labels
    firstSeries.data.forEach((point, index) => {
      const x = padding + (index + 0.5) * (chartWidth / firstSeries.data.length);
      ctx.fillText(point.x.toString(), x, padding + chartHeight + 20);
    });

    // Y-axis labels
    ctx.textAlign = 'right';
    for (let i = 0; i <= 5; i++) {
      const y = padding + (chartHeight * i) / 5;
      const value = maxY - ((maxY - minY) * i) / 5;
      ctx.fillText(value.toFixed(0), padding - 10, y + 4);
    }
  };

  const drawLineChart = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, chartData: ChartSeries[]) => {
    if (!chartData.length) return;

    const padding = 60;
    const chartWidth = canvas.width - 2 * padding;
    const chartHeight = canvas.height - 2 * padding;
    
    const allPoints = chartData.flatMap(series => series.data);
    const maxY = Math.max(...allPoints.map(point => point.y));
    const minY = Math.min(...allPoints.map(point => point.y));

    // Draw grid
    ctx.strokeStyle = '#e5e7eb';
    ctx.lineWidth = 1;
    for (let i = 0; i <= 5; i++) {
      const y = padding + (chartHeight * i) / 5;
      ctx.beginPath();
      ctx.moveTo(padding, y);
      ctx.lineTo(padding + chartWidth, y);
      ctx.stroke();
    }

    // Draw lines
    chartData.forEach((series, seriesIndex) => {
      if (!series.visible) return;
      
      const color = series.color || widget.config.color_scheme[seriesIndex % widget.config.color_scheme.length];
      ctx.strokeStyle = color;
      ctx.lineWidth = 2;
      ctx.beginPath();

      series.data.forEach((point, pointIndex) => {
        const x = padding + (pointIndex * chartWidth) / (series.data.length - 1);
        const y = padding + chartHeight - ((point.y - minY) / (maxY - minY)) * chartHeight;

        if (pointIndex === 0) {
          ctx.moveTo(x, y);
        } else {
          ctx.lineTo(x, y);
        }
      });

      ctx.stroke();

      // Draw points
      ctx.fillStyle = color;
      series.data.forEach((point, pointIndex) => {
        const x = padding + (pointIndex * chartWidth) / (series.data.length - 1);
        const y = padding + chartHeight - ((point.y - minY) / (maxY - minY)) * chartHeight;
        
        ctx.beginPath();
        ctx.arc(x, y, 4, 0, 2 * Math.PI);
        ctx.fill();
      });
    });

    // Draw axes
    ctx.strokeStyle = '#374151';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(padding, padding);
    ctx.lineTo(padding, padding + chartHeight);
    ctx.lineTo(padding + chartWidth, padding + chartHeight);
    ctx.stroke();
  };

  const drawPieChart = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, chartData: ChartSeries[]) => {
    if (!chartData.length) return;

    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const radius = Math.min(canvas.width, canvas.height) / 3;

    const firstSeries = chartData[0];
    const total = firstSeries.data.reduce((sum, point) => sum + point.y, 0);
    
    let startAngle = -Math.PI / 2;

    firstSeries.data.forEach((point, index) => {
      const sliceAngle = (point.y / total) * 2 * Math.PI;
      const color = widget.config.color_scheme[index % widget.config.color_scheme.length];

      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(centerX, centerY);
      ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle);
      ctx.closePath();
      ctx.fill();

      // Draw slice border
      ctx.strokeStyle = '#ffffff';
      ctx.lineWidth = 2;
      ctx.stroke();

      // Draw labels
      const labelAngle = startAngle + sliceAngle / 2;
      const labelX = centerX + Math.cos(labelAngle) * (radius + 30);
      const labelY = centerY + Math.sin(labelAngle) * (radius + 30);
      
      ctx.fillStyle = '#374151';
      ctx.font = '12px sans-serif';
      ctx.textAlign = 'center';
      ctx.fillText(point.x.toString(), labelX, labelY);
      
      const percentage = ((point.y / total) * 100).toFixed(1);
      ctx.fillText(`${percentage}%`, labelX, labelY + 15);

      startAngle += sliceAngle;
    });
  };

  const drawAreaChart = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, chartData: ChartSeries[]) => {
    if (!chartData.length) return;

    const padding = 60;
    const chartWidth = canvas.width - 2 * padding;
    const chartHeight = canvas.height - 2 * padding;
    
    const allPoints = chartData.flatMap(series => series.data);
    const maxY = Math.max(...allPoints.map(point => point.y));
    const minY = Math.min(...allPoints.map(point => point.y));

    chartData.forEach((series, seriesIndex) => {
      if (!series.visible) return;
      
      const color = series.color || widget.config.color_scheme[seriesIndex % widget.config.color_scheme.length];
      
      // Create gradient
      const gradient = ctx.createLinearGradient(0, padding, 0, padding + chartHeight);
      gradient.addColorStop(0, color + '80'); // Semi-transparent
      gradient.addColorStop(1, color + '10'); // Very transparent

      ctx.fillStyle = gradient;
      ctx.beginPath();

      // Start from bottom-left
      const firstX = padding;
      const firstY = padding + chartHeight;
      ctx.moveTo(firstX, firstY);

      // Draw the area path
      series.data.forEach((point, pointIndex) => {
        const x = padding + (pointIndex * chartWidth) / (series.data.length - 1);
        const y = padding + chartHeight - ((point.y - minY) / (maxY - minY)) * chartHeight;
        ctx.lineTo(x, y);
      });

      // Close the path at bottom-right
      const lastX = padding + chartWidth;
      const lastY = padding + chartHeight;
      ctx.lineTo(lastX, lastY);
      ctx.closePath();
      ctx.fill();

      // Draw the line on top
      ctx.strokeStyle = color;
      ctx.lineWidth = 2;
      ctx.beginPath();
      series.data.forEach((point, pointIndex) => {
        const x = padding + (pointIndex * chartWidth) / (series.data.length - 1);
        const y = padding + chartHeight - ((point.y - minY) / (maxY - minY)) * chartHeight;

        if (pointIndex === 0) {
          ctx.moveTo(x, y);
        } else {
          ctx.lineTo(x, y);
        }
      });
      ctx.stroke();
    });
  };

  const handleExport = () => {
    if (onExport) {
      onExport(selectedExportFormat);
    }
  };

  const handleFullscreen = () => {
    setIsFullscreen(!isFullscreen);
    if (onFullscreen) {
      onFullscreen();
    }
  };

  const renderLegend = () => {
    if (!widget.config.show_legend || !data.length) return null;

    return (
      <div className="flex flex-wrap gap-4 mt-4">
        {data.map((series, index) => (
          <div key={series.id} className="flex items-center gap-2">
            <div 
              className="w-3 h-3 rounded-full"
              style={{ 
                backgroundColor: series.color || widget.config.color_scheme[index % widget.config.color_scheme.length] 
              }}
            />
            <span className="text-sm text-[var(--text-secondary)]">{series.name}</span>
          </div>
        ))}
      </div>
    );
  };

  const renderControls = () => {
    if (!showControls || !interactive) return null;

    return (
      <div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
        <Button
          variant="ghost"
          size="sm"
          onClick={() => setIsConfigModalOpen(true)}
          title="Configurar gráfico"
        >
          ⚙️
        </Button>
        
        <Select
          value={selectedExportFormat}
          onChange={(e) => setSelectedExportFormat(e.target.value as ExportFormat)}
          className="w-20 text-xs"
        >
          {EXPORT_FORMATS.map(format => (
            <option key={format} value={format}>{format.toUpperCase()}</option>
          ))}
        </Select>
        
        <Button
          variant="ghost"
          size="sm"
          onClick={handleExport}
          title="Exportar gráfico"
        >
          📥
        </Button>
        
        <Button
          variant="ghost"
          size="sm"
          onClick={handleFullscreen}
          title="Pantalla completa"
        >
          {isFullscreen ? '📋' : '🔍'}
        </Button>
        
        {onRefresh && (
          <Button
            variant="ghost"
            size="sm"
            onClick={onRefresh}
            disabled={loading}
            title="Actualizar datos"
          >
            🔄
          </Button>
        )}
      </div>
    );
  };

  if (error) {
    return (
      <Card className={`p-6 ${className}`}>
        <div className="text-center">
          <p className="text-[var(--color-error)] font-medium">Error al cargar el gráfico</p>
          <p className="text-sm text-[var(--text-tertiary)] mt-1">{error}</p>
          {onRefresh && (
            <Button variant="outline" size="sm" onClick={onRefresh} className="mt-3">
              Reintentar
            </Button>
          )}
        </div>
      </Card>
    );
  }

  return (
    <>
      <Card className={`group relative ${className}`} style={{ 
        width: chartDimensions.width,
        height: isFullscreen ? '90vh' : chartDimensions.height 
      }}>
        {/* Header */}
        <div className="flex items-start justify-between p-4 pb-2">
          <div className="flex-1">
            {showTitle && (
              <h3 className="text-lg font-semibold text-[var(--text-primary)]">
                {widget.title}
              </h3>
            )}
            {showSubtitle && widget.subtitle && (
              <p className="text-sm text-[var(--text-secondary)] mt-1">
                {widget.subtitle}
              </p>
            )}
          </div>
          
          {renderControls()}
        </div>

        {/* Chart Area */}
        <div className="px-4 pb-4" style={{ height: `calc(100% - 80px)` }}>
          {loading ? (
            <div className="flex items-center justify-center h-full">
              <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
            </div>
          ) : data.length === 0 ? (
            <div className="flex items-center justify-center h-full">
              <div className="text-center">
                <p className="text-[var(--text-tertiary)]">No hay datos disponibles</p>
                <p className="text-sm text-[var(--text-tertiary)] mt-1">
                  Ajusta los filtros o verifica la conexión de datos
                </p>
              </div>
            </div>
          ) : (
            <div className="h-full">
              <canvas
                ref={canvasRef}
                className="w-full h-full"
                style={{ maxHeight: '100%' }}
              />
              {renderLegend()}
            </div>
          )}
        </div>

        {/* Last Updated */}
        {widget.last_updated && (
          <div className="absolute bottom-2 right-2 text-xs text-[var(--text-tertiary)]">
            Actualizado: {new Date(widget.last_updated).toLocaleTimeString()}
          </div>
        )}
      </Card>

      {/* Configuration Modal */}
      <Modal
        isOpen={isConfigModalOpen}
        onClose={() => setIsConfigModalOpen(false)}
        title="Configuración del Gráfico"
      >
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
              Tipo de gráfico
            </label>
            <Select
              value={widget.type}
              onChange={(e) => {
                if (onConfigChange) {
                  onConfigChange({ visualization_type: e.target.value as ChartType });
                }
              }}
            >
              {Object.entries(CHART_TYPE_LABELS).map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </Select>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="flex items-center">
                <input
                  type="checkbox"
                  checked={widget.config.show_legend}
                  onChange={(e) => {
                    if (onConfigChange) {
                      onConfigChange({ show_legend: e.target.checked });
                    }
                  }}
                  className="mr-2"
                />
                Mostrar leyenda
              </label>
            </div>
            
            <div>
              <label className="flex items-center">
                <input
                  type="checkbox"
                  checked={widget.config.show_grid}
                  onChange={(e) => {
                    if (onConfigChange) {
                      onConfigChange({ show_grid: e.target.checked });
                    }
                  }}
                  className="mr-2"
                />
                Mostrar cuadrícula
              </label>
            </div>
            
            <div>
              <label className="flex items-center">
                <input
                  type="checkbox"
                  checked={widget.config.show_tooltips}
                  onChange={(e) => {
                    if (onConfigChange) {
                      onConfigChange({ show_tooltips: e.target.checked });
                    }
                  }}
                  className="mr-2"
                />
                Mostrar tooltips
              </label>
            </div>
            
            <div>
              <label className="flex items-center">
                <input
                  type="checkbox"
                  checked={widget.config.animation_enabled}
                  onChange={(e) => {
                    if (onConfigChange) {
                      onConfigChange({ animation_enabled: e.target.checked });
                    }
                  }}
                  className="mr-2"
                />
                Animaciones
              </label>
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
              Posición de la leyenda
            </label>
            <Select
              value={widget.config.legend_position}
              onChange={(e) => {
                if (onConfigChange) {
                  onConfigChange({ legend_position: e.target.value as any });
                }
              }}
            >
              <option value="top">Arriba</option>
              <option value="bottom">Abajo</option>
              <option value="left">Izquierda</option>
              <option value="right">Derecha</option>
            </Select>
          </div>

          <div className="flex justify-end gap-2 pt-4 border-t">
            <Button
              variant="outline"
              onClick={() => setIsConfigModalOpen(false)}
            >
              Cancelar
            </Button>
            <Button
              variant="primary"
              onClick={() => {
                setIsConfigModalOpen(false);
                if (onRefresh) onRefresh();
              }}
            >
              Aplicar cambios
            </Button>
          </div>
        </div>
      </Modal>
    </>
  );
};

export default ChartWidget;