import React, { memo, useMemo, useCallback } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import { formatSensorValue, getSensorPrecision } from '../utils/formatters';

interface SensorChartProps {
  title: string;
  data: any[];
  dataKeys: string[];
  colors: string[];
  names?: string[];
  height?: number;
  yAxisId?: string;
  rightYAxisId?: string;
  rightDataKeys?: string[];
  rightColors?: string[];
  rightNames?: string[];
}

// 데이터 유효성 검증 함수 - 강화된 검증
const validateChartData = (data: any[], dataKeys: string[], rightDataKeys: string[]): boolean => {
  if (!data || !Array.isArray(data) || data.length === 0) {
    return false;
  }

  // 모든 데이터 항목이 유효한지 확인
  return data.every(item => {
    if (!item || typeof item !== 'object' || !item.device_id) {
      return false;
    }

    // 모든 dataKeys가 유효한 숫자인지 확인
    const allKeys = [...dataKeys, ...rightDataKeys];
    return allKeys.every(key => {
      const value = item[key];
      return typeof value === 'number' && !isNaN(value) && isFinite(value);
    });
  });
};

// 기본 더미 데이터 생성 함수
const createDefaultData = (dataKeys: string[], rightDataKeys: string[]) => {
  const allKeys = [...dataKeys, ...rightDataKeys];
  const defaultItem: any = {
    device_id: 'No Data'
  };
  
  allKeys.forEach(key => {
    defaultItem[key] = 0;
  });
  
  return [defaultItem];
};

// 안전한 숫자 변환 함수
const safeNumber = (value: any, defaultValue: number = 0): number => {
  if (value === null || value === undefined) {
    return defaultValue;
  }
  
  const num = Number(value);
  if (typeof num === 'number' && !isNaN(num) && isFinite(num)) {
    return num;
  }
  
  return defaultValue;
};

const SensorChart: React.FC<SensorChartProps> = memo(({
  title,
  data,
  dataKeys,
  colors,
  names,
  height = 300,
  yAxisId,
  rightYAxisId,
  rightDataKeys = [],
  rightColors = [],
  rightNames = []
}) => {
  // 차트 데이터 메모이제이션 및 검증 - 의존성 배열 최적화
  const chartData = useMemo(() => {
    // 데이터가 없거나 빈 배열인 경우 기본 데이터 반환
    if (!data || !Array.isArray(data) || data.length === 0) {
      return createDefaultData(dataKeys, rightDataKeys);
    }

    // 데이터 유효성 검사 및 정리
    const processedData = data
      .filter(item => item && typeof item === 'object' && item.device_id)
      .map(item => {
        const processedItem: any = {
          device_id: item.device_id || 'Unknown',
        };

        // 모든 dataKeys에 대해 안전하게 값 추출
        dataKeys.forEach(key => {
          processedItem[key] = safeNumber(item[key], 0);
        });

        // 모든 rightDataKeys에 대해 안전하게 값 추출
        rightDataKeys.forEach(key => {
          processedItem[key] = safeNumber(item[key], 0);
        });

        return processedItem;
      });

    // 처리된 데이터가 비어있으면 기본 데이터 반환
    if (processedData.length === 0) {
      return createDefaultData(dataKeys, rightDataKeys);
    }

    return processedData;
  }, [data, dataKeys, rightDataKeys]);

  // 데이터 유효성 검사 - 메모이제이션 최적화
  const isValidData = useMemo(() => {
    return validateChartData(chartData, dataKeys, rightDataKeys);
  }, [chartData, dataKeys, rightDataKeys]);

  // 툴팁 포맷터 메모이제이션 - useCallback 사용
  const tooltipFormatter = useCallback((value: any, name: string) => {
    const sensorType = name.toLowerCase().replace(/\s+/g, '');
    return [formatSensorValue(value, getSensorPrecision(sensorType)), name];
  }, []);

  // Y축 설정 메모이제이션
  const yAxisConfig = useMemo(() => {
    const config = {
      hasLeftYAxis: false,
      hasRightYAxis: false,
      leftYAxis: null as React.ReactElement | null,
      rightYAxis: null as React.ReactElement | null,
      defaultYAxis: null as React.ReactElement | null
    };

    if (yAxisId) {
      config.hasLeftYAxis = true;
      config.leftYAxis = <YAxis yAxisId={yAxisId} stroke="#6B7280" tick={{ fill: '#6B7280' }} />;
    }

    if (rightYAxisId) {
      config.hasRightYAxis = true;
      config.rightYAxis = <YAxis yAxisId={rightYAxisId} orientation="right" stroke="#6B7280" tick={{ fill: '#6B7280' }} />;
    }

    if (!yAxisId && !rightYAxisId) {
      config.defaultYAxis = <YAxis stroke="#6B7280" tick={{ fill: '#6B7280' }} />;
    }

    return config;
  }, [yAxisId, rightYAxisId]);

  // 라인 컴포넌트 메모이제이션
  const leftLines = useMemo(() => {
    return dataKeys.map((key, index) => {
      // 데이터 키가 실제로 존재하는지 확인
      const hasData = chartData.some(item => typeof item[key] === 'number' && !isNaN(item[key]));
      if (!hasData) return null;
      
      return (
        <Line
          key={key}
          yAxisId={yAxisId}
          type="monotone"
          dataKey={key}
          stroke={colors[index] || '#3b82f6'}
          strokeWidth={2}
          name={names?.[index] || key}
          dot={false}
        />
      );
    }).filter(Boolean);
  }, [dataKeys, colors, names, yAxisId, chartData]);

  const rightLines = useMemo(() => {
    return rightDataKeys.map((key, index) => {
      // 데이터 키가 실제로 존재하는지 확인
      const hasData = chartData.some(item => typeof item[key] === 'number' && !isNaN(item[key]));
      if (!hasData) return null;
      
      return (
        <Line
          key={`right-${key}`}
          yAxisId={rightYAxisId}
          type="monotone"
          dataKey={key}
          stroke={rightColors[index] || '#10b981'}
          strokeWidth={2}
          name={rightNames?.[index] || key}
          dot={false}
        />
      );
    }).filter(Boolean);
  }, [rightDataKeys, rightColors, rightNames, rightYAxisId, chartData]);

  // 데이터가 없거나 유효하지 않은 경우 안내 메시지 표시
  if (chartData.length === 0 || !isValidData) {
    return (
      <div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
        <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-4">{title}</h3>
        <div className="flex items-center justify-center h-[300px]">
          <div className="text-center">
            <div className="text-gray-400 mb-2">
              <svg className="w-8 h-8 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
              </svg>
            </div>
            <p className="text-sm text-gray-500">
              {chartData.length === 0 ? '데이터가 없습니다' : '유효한 데이터가 없습니다'}
            </p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
      <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-4">{title}</h3>
      <ResponsiveContainer width="100%" height={height}>
        <LineChart data={chartData} margin={{ top: 5, right: 20, left: 0, bottom: 5 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
          <XAxis 
            dataKey="device_id" 
            stroke="#6B7280"
            tick={{ fill: '#6B7280' }}
          />
          
          {/* Y축 설정 - 메모이제이션된 설정 사용 */}
          {yAxisConfig.leftYAxis}
          {yAxisConfig.rightYAxis}
          {yAxisConfig.defaultYAxis}
          
          <Tooltip 
            formatter={tooltipFormatter}
            contentStyle={{
              backgroundColor: '#1F2937',
              border: '1px solid #374151',
              borderRadius: '8px',
              color: '#F9FAFB'
            }}
          />
          <Legend />
          
          {/* 메모이제이션된 라인 컴포넌트들 */}
          {leftLines}
          {rightLines}
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
});

SensorChart.displayName = 'SensorChart';

export default SensorChart; 