import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import ChartComponent from '../components/LineChart.js';
import '@testing-library/jest-dom/extend-expect';

describe('ChartComponent', () => {
  const mockGraphData = [
    {
      EndTime: '2023-05-15T12:34:56',
      ActiveLoginCount: 210,
      LoginCount: 200,
      ApplicationCount: 5,
      CallCount: 2
    },
    {
      EndTime: '2023-05-15T13:45:00',
      ActiveLoginCount: 180,
      LoginCount: 175,
      ApplicationCount: 10,
      CallCount: 4
    },
    {
      EndTime: '2023-05-15T14:30:22',
      ActiveLoginCount: 220,
      LoginCount: 215,
      ApplicationCount: 8,
      CallCount: 3
    }
  ];

  // Test 1: Component renders without crashing
  it('renders without crashing', () => {
    render(<ChartComponent graphData={mockGraphData} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 2: Renders with empty array
  it('renders with empty graphData array', () => {
    render(<ChartComponent graphData={[]} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 3: Renders with undefined data
  it('renders with undefined graphData', () => {
    render(<ChartComponent graphData={undefined} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 4: Renders with null data
  it('renders with null graphData', () => {
    render(<ChartComponent graphData={null} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 5: Uses default props when no graphData provided
  it('uses default props when graphData is not provided', () => {
    const { container } = render(<ChartComponent />);
    expect(container.querySelector('#chart')).toBeInTheDocument();
  });

  // Test 6: Formats time correctly from EndTime
  it('extracts time in HH:MM format from EndTime', async () => {
    const { rerender } = render(<ChartComponent graphData={mockGraphData} />);
    
    await waitFor(() => {
      expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
    });

    // Verify component processed the data by checking it renders
    const chartElement = screen.getByTestId('mock-chart');
    expect(chartElement).toBeInTheDocument();
  });

  // Test 7: Handles data with missing EndTime
  it('handles data with missing EndTime gracefully', () => {
    const dataWithMissingTime = [
      {
        ActiveLoginCount: 100,
        LoginCount: 90,
        EndTime: undefined
      }
    ];
    render(<ChartComponent graphData={dataWithMissingTime} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 8: Handles data with missing ActiveLoginCount
  it('handles data with missing ActiveLoginCount', () => {
    const dataWithMissingCount = [
      {
        EndTime: '2023-05-15T12:34:56',
        LoginCount: 200
      }
    ];
    render(<ChartComponent graphData={dataWithMissingCount} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 9: Handles data with missing LoginCount
  it('handles data with missing LoginCount', () => {
    const dataWithMissingLoginCount = [
      {
        EndTime: '2023-05-15T12:34:56',
        ActiveLoginCount: 210
      }
    ];
    render(<ChartComponent graphData={dataWithMissingLoginCount} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 10: Processes multiple data points
  it('processes multiple data points correctly', () => {
    const multipleDataPoints = Array.from({ length: 10 }, (_, i) => ({
      EndTime: `2023-05-15T${String(i).padStart(2, '0')}:00:00`,
      ActiveLoginCount: 100 + i * 10,
      LoginCount: 90 + i * 10
    }));
    
    render(<ChartComponent graphData={multipleDataPoints} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 11: Component can be re-rendered with new data
  it('re-renders correctly when graphData prop changes', () => {
    const { rerender } = render(<ChartComponent graphData={mockGraphData} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();

    const newData = [
      {
        EndTime: '2023-05-16T10:00:00',
        ActiveLoginCount: 500,
        LoginCount: 480
      }
    ];

    rerender(<ChartComponent graphData={newData} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 12: Handles edge case with single data point
  it('handles single data point', () => {
    const singleDataPoint = [
      {
        EndTime: '2023-05-15T12:34:56',
        ActiveLoginCount: 150,
        LoginCount: 140
      }
    ];
    
    render(<ChartComponent graphData={singleDataPoint} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 13: Returns div with correct id
  it('returns chart div with correct id', () => {
    const { container } = render(<ChartComponent graphData={mockGraphData} />);
    const chartDiv = container.querySelector('#chart');
    expect(chartDiv).toBeInTheDocument();
  });

  // Test 14: Handles data with extra properties
  it('handles data with extra properties', () => {
    const dataWithExtra = [
      {
        EndTime: '2023-05-15T12:34:56',
        ActiveLoginCount: 210,
        LoginCount: 200,
        ExtraField: 'extra',
        AnotherField: 123
      }
    ];
    
    render(<ChartComponent graphData={dataWithExtra} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 15: Handles zero values in counts
  it('handles zero values in counts', () => {
    const zeroDataPoints = [
      {
        EndTime: '2023-05-15T12:34:56',
        ActiveLoginCount: 0,
        LoginCount: 0
      }
    ];
    
    render(<ChartComponent graphData={zeroDataPoints} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 16: PropTypes validation
  it('validates PropTypes correctly', () => {
    const expectedPropTypes = ChartComponent.propTypes;
    expect(expectedPropTypes).toBeDefined();
    expect(expectedPropTypes.graphData).toBeDefined();
  });

  // Test 17: Default props are set correctly
  it('has default props set', () => {
    const expectedDefaultProps = ChartComponent.defaultProps;
    expect(expectedDefaultProps).toBeDefined();
    expect(expectedDefaultProps.graphData).toEqual([]);
  });

  // Test 18: Handles large dataset
  it('handles large dataset with 100 data points', () => {
    const largeDataset = Array.from({ length: 100 }, (_, i) => ({
      EndTime: `2023-05-15T${String(i % 24).padStart(2, '0')}:${String(i % 60).padStart(2, '0')}:00`,
      ActiveLoginCount: Math.random() * 1000,
      LoginCount: Math.random() * 1000
    }));
    
    render(<ChartComponent graphData={largeDataset} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });

  // Test 19: State updates when data changes
  it('state updates correctly when graphData prop changes', async () => {
    const { rerender } = render(<ChartComponent graphData={[]} />);
    
    await waitFor(() => {
      expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
    });

    rerender(<ChartComponent graphData={mockGraphData} />);

    await waitFor(() => {
      expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
    });
  });

  // Test 20: Handles special characters in EndTime
  it('handles data with various EndTime formats', () => {
    const specialData = [
      { EndTime: '2023-05-15T23:59:59', ActiveLoginCount: 100, LoginCount: 90 },
      { EndTime: '2023-05-15T00:00:01', ActiveLoginCount: 50, LoginCount: 45 }
    ];
    
    render(<ChartComponent graphData={specialData} />);
    expect(screen.getByTestId('mock-chart')).toBeInTheDocument();
  });
});
