import { render, screen, waitFor } from '@testing-library/react';
import WeeklySleepChart from '@/components/analytics/WeeklySleepChart';
import apiClient from '@/lib/api/client';

jest.mock('@/lib/api/client');
const mockApiClient = apiClient as jest.Mocked<typeof apiClient>;

describe('WeeklySleepChart', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('should render loading state initially', () => {
    mockApiClient.get.mockImplementation(() => new Promise(() => {}));

    render(<WeeklySleepChart />);

    expect(screen.getByRole('progressbar')).toBeInTheDocument();
  });

  it('should render sleep data successfully', async () => {
    const mockSleepData = [
      {
        id: 'slp_1',
        startTime: new Date('2024-01-01T20:00:00Z').toISOString(),
        endTime: new Date('2024-01-02T06:00:00Z').toISOString(),
        duration: 600, // 10 hours
        quality: 4,
      },
      {
        id: 'slp_2',
        startTime: new Date('2024-01-02T20:00:00Z').toISOString(),
        endTime: new Date('2024-01-03T07:00:00Z').toISOString(),
        duration: 660, // 11 hours
        quality: 5,
      },
    ];

    mockApiClient.get.mockResolvedValueOnce({
      data: {
        data: mockSleepData,
      },
    });

    render(<WeeklySleepChart />);

    await waitFor(() => {
      expect(screen.getByText('Weekly Sleep Patterns')).toBeInTheDocument();
    });

    expect(screen.getByText('Total Sleep Hours')).toBeInTheDocument();
    expect(screen.getByText('Sleep Quality Trend')).toBeInTheDocument();
  });

  it('should handle API error gracefully', async () => {
    mockApiClient.get.mockRejectedValueOnce({
      response: {
        data: {
          message: 'Failed to fetch sleep data',
        },
      },
    });

    render(<WeeklySleepChart />);

    await waitFor(() => {
      expect(screen.getByRole('alert')).toBeInTheDocument();
      expect(screen.getByText('Failed to fetch sleep data')).toBeInTheDocument();
    });
  });

  it('should aggregate sleep data by day', async () => {
    const mockSleepData = [
      {
        id: 'slp_1',
        startTime: new Date('2024-01-01T20:00:00Z').toISOString(),
        duration: 600, // Night sleep
        quality: 4,
      },
      {
        id: 'slp_2',
        startTime: new Date('2024-01-01T14:00:00Z').toISOString(),
        duration: 120, // Nap
        quality: 3,
      },
    ];

    mockApiClient.get.mockResolvedValueOnce({
      data: {
        data: mockSleepData,
      },
    });

    render(<WeeklySleepChart />);

    await waitFor(() => {
      expect(mockApiClient.get).toHaveBeenCalledWith(
        '/api/v1/activities/sleep',
        expect.objectContaining({
          params: expect.objectContaining({
            startDate: expect.any(String),
            endDate: expect.any(String),
          }),
        })
      );
    });
  });

  it('should display 7 days of data', async () => {
    mockApiClient.get.mockResolvedValueOnce({
      data: {
        data: [],
      },
    });

    render(<WeeklySleepChart />);

    await waitFor(() => {
      expect(screen.getByText('Weekly Sleep Patterns')).toBeInTheDocument();
    });

    // Chart should request exactly 7 days of data
    expect(mockApiClient.get).toHaveBeenCalledWith(
      '/api/v1/activities/sleep',
      expect.objectContaining({
        params: expect.any(Object),
      })
    );
  });

  it('should calculate quality average correctly', async () => {
    const mockSleepData = [
      {
        id: 'slp_1',
        startTime: new Date('2024-01-01T20:00:00Z').toISOString(),
        duration: 600,
        quality: 4,
      },
      {
        id: 'slp_2',
        startTime: new Date('2024-01-01T14:00:00Z').toISOString(),
        duration: 120,
        quality: 2,
      },
    ];

    mockApiClient.get.mockResolvedValueOnce({
      data: {
        data: mockSleepData,
      },
    });

    render(<WeeklySleepChart />);

    await waitFor(() => {
      expect(screen.getByText('Sleep Quality Trend')).toBeInTheDocument();
    });

    // Average quality should be (4 + 2) / 2 = 3
  });
});
