import React from 'react';
import { render, screen } from '@testing-library/react';
import SensorChart from '../SensorChart';

// Recharts 컴포넌트들을 모킹
jest.mock('recharts', () => ({
  LineChart: ({ children, data }: any) => (
    <div data-testid="line-chart" data-chart-data={JSON.stringify(data)}>
      {children}
    </div>
  ),
  Line: ({ dataKey, name }: any) => (
    <div data-testid={`line-${dataKey}`} data-name={name}>
      Line: {dataKey}
    </div>
  ),
  XAxis: ({ dataKey }: any) => (
    <div data-testid="x-axis" data-key={dataKey}>
      XAxis: {dataKey}
    </div>
  ),
  YAxis: ({ yAxisId }: any) => (
    <div data-testid="y-axis" data-y-axis-id={yAxisId}>
      YAxis
    </div>
  ),
  CartesianGrid: () => <div data-testid="cartesian-grid">CartesianGrid</div>,
  Tooltip: ({ formatter }: any) => (
    <div data-testid="tooltip" data-formatter={formatter ? 'true' : 'false'}>
      Tooltip
    </div>
  ),
  Legend: () => <div data-testid="legend">Legend</div>,
  ResponsiveContainer: ({ children }: any) => (
    <div data-testid="responsive-container">
      {children}
    </div>
  ),
}));

describe('SensorChart', () => {
  const defaultProps = {
    title: '테스트 차트',
    dataKeys: ['temperature', 'humidity'],
    colors: ['#3b82f6', '#10b981'],
    names: ['온도', '습도']
  };

  describe('빈 데이터 처리', () => {
    it('빈 배열이 전달되면 기본 데이터를 사용하여 차트를 렌더링한다', () => {
      render(<SensorChart {...defaultProps} data={[]} />);

      // 차트가 렌더링되는지 확인
      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      
      // 기본 데이터가 사용되는지 확인
      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      expect(parsedData).toHaveLength(1);
      expect(parsedData[0]).toEqual({
        device_id: 'No Data',
        temperature: 0,
        humidity: 0
      });
    });

    it('null 데이터가 전달되면 기본 데이터를 사용하여 차트를 렌더링한다', () => {
      render(<SensorChart {...defaultProps} data={null as any} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      
      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      expect(parsedData).toHaveLength(1);
      expect(parsedData[0].device_id).toBe('No Data');
    });

    it('undefined 데이터가 전달되면 기본 데이터를 사용하여 차트를 렌더링한다', () => {
      render(<SensorChart {...defaultProps} data={undefined as any} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      
      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      expect(parsedData).toHaveLength(1);
      expect(parsedData[0].device_id).toBe('No Data');
    });

    it('유효하지 않은 데이터 구조가 전달되면 기본 데이터를 사용한다', () => {
      const invalidData = [
        { invalid_key: 'test' }, // device_id가 없음
        { device_id: 'test', temperature: 'invalid' }, // 숫자가 아닌 값
        { device_id: 'test', humidity: NaN }, // NaN 값
        { device_id: 'test', temperature: Infinity } // Infinity 값
      ];

      render(<SensorChart {...defaultProps} data={invalidData} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      
      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      // device_id가 있는 데이터는 처리되지만, 유효하지 않은 값들은 0으로 변환됨
      expect(parsedData).toHaveLength(3); // device_id가 있는 3개 데이터
      expect(parsedData[0].device_id).toBe('test');
      expect(parsedData[0].temperature).toBe(0); // 'invalid' 문자열은 0으로 변환
      expect(parsedData[0].humidity).toBe(0);
      expect(parsedData[1].humidity).toBe(0); // NaN은 0으로 변환
      expect(parsedData[2].temperature).toBe(0); // Infinity는 0으로 변환
    });
  });

  describe('데이터 유효성 검증', () => {
    it('유효한 데이터가 전달되면 정상적으로 차트를 렌더링한다', () => {
      const validData = [
        {
          device_id: 'sensor-001',
          temperature: 25.5,
          humidity: 60.0
        }
      ];

      render(<SensorChart {...defaultProps} data={validData} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      expect(screen.getByTestId('line-temperature')).toBeInTheDocument();
      expect(screen.getByTestId('line-humidity')).toBeInTheDocument();
    });

    it('일부 데이터가 유효하지 않으면 유효한 데이터만 처리한다', () => {
      const mixedData = [
        {
          device_id: 'sensor-001',
          temperature: 25.5,
          humidity: 60.0
        },
        {
          device_id: 'sensor-002',
          temperature: null,
          humidity: undefined
        }
      ];

      render(<SensorChart {...defaultProps} data={mixedData} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      
      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      expect(parsedData).toHaveLength(2);
      expect(parsedData[0].temperature).toBe(25.5);
      expect(parsedData[0].humidity).toBe(60.0);
      expect(parsedData[1].temperature).toBe(0); // null 값은 0으로 변환
      expect(parsedData[1].humidity).toBe(0); // undefined 값은 0으로 변환
    });
  });

  describe('오른쪽 Y축 데이터 처리', () => {
    it('오른쪽 Y축 데이터가 있는 경우 정상적으로 처리한다', () => {
      const propsWithRightAxis = {
        ...defaultProps,
        rightDataKeys: ['pressure'],
        rightColors: ['#f59e0b'],
        rightNames: ['기압'],
        rightYAxisId: 'right'
      };

      const data = [
        {
          device_id: 'sensor-001',
          temperature: 25.5,
          humidity: 60.0,
          pressure: 1013.25
        }
      ];

      render(<SensorChart {...propsWithRightAxis} data={data} />);

      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      expect(screen.getByTestId('line-pressure')).toBeInTheDocument();
    });

    it('오른쪽 Y축 데이터가 없으면 기본 데이터를 사용한다', () => {
      const propsWithRightAxis = {
        ...defaultProps,
        rightDataKeys: ['pressure'],
        rightColors: ['#f59e0b'],
        rightNames: ['기압'],
        rightYAxisId: 'right'
      };

      render(<SensorChart {...propsWithRightAxis} data={[]} />);

      const chartData = screen.getByTestId('line-chart').getAttribute('data-chart-data');
      const parsedData = JSON.parse(chartData || '[]');
      
      expect(parsedData[0]).toEqual({
        device_id: 'No Data',
        temperature: 0,
        humidity: 0,
        pressure: 0
      });
    });
  });

  describe('컴포넌트 렌더링', () => {
    it('제목이 올바르게 표시된다', () => {
      render(<SensorChart {...defaultProps} data={[]} />);
      expect(screen.getByText('테스트 차트')).toBeInTheDocument();
    });

    it('기본 높이가 300px로 설정된다', () => {
      render(<SensorChart {...defaultProps} data={[]} />);
      expect(screen.getByTestId('responsive-container')).toBeInTheDocument();
    });

    it('사용자 정의 높이가 적용된다', () => {
      render(<SensorChart {...defaultProps} data={[]} height={400} />);
      expect(screen.getByTestId('responsive-container')).toBeInTheDocument();
    });
  });
}); 