// src/features/charts/PriceHistoryChart.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { PriceHistoryChart } from './PriceHistoryChart';
import { useUserData } from '../../hooks/useUserData';
import * as apiClient from '../../services/apiClient';
import type { MasterGroceryItem, HistoricalPriceDataPoint } from '../../types';

// Mock the apiClient
vi.mock('../../services/apiClient');

// Mock the useUserData hook
vi.mock('../../hooks/useUserData');
const mockedUseUserData = useUserData as Mock;

// Mock the logger
vi.mock('../../services/logger', () => ({
  logger: {
    error: vi.fn(),
  },
}));

// Mock the recharts library to prevent rendering complex SVGs in jsdom
vi.mock('recharts', () => ({
  ResponsiveContainer: ({ children }: { children: React.ReactNode }) => <div data-testid="responsive-container">{children}</div>,
  LineChart: ({ children }: { children: React.ReactNode }) => <div data-testid="line-chart">{children}</div>,
  CartesianGrid: () => <div data-testid="cartesian-grid" />,
  XAxis: () => <div data-testid="x-axis" />,
  YAxis: () => <div data-testid="y-axis" />,
  Tooltip: () => <div data-testid="tooltip" />,
  Legend: () => <div data-testid="legend" />,
  // Fix: Use dataKey if name is not explicitly provided, as the component relies on dataKey
  Line: ({ name, dataKey }: { name?: string; dataKey?: string }) => <div data-testid={`line-${name || dataKey}`} />,
}));

const mockWatchedItems: MasterGroceryItem[] = [
  { master_grocery_item_id: 1, name: 'Organic Bananas', created_at: '2024-01-01' },
  { master_grocery_item_id: 2, name: 'Almond Milk', created_at: '2024-01-01' },
];

const mockPriceHistory: HistoricalPriceDataPoint[] = [
  { master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 110 },
  { master_item_id: 1, summary_date: '2024-10-08', avg_price_in_cents: 99 },
  { master_item_id: 2, summary_date: '2024-10-01', avg_price_in_cents: 350 },
  { master_item_id: 2, summary_date: '2024-10-08', avg_price_in_cents: 349 },
];

describe('PriceHistoryChart', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    // Provide a default successful mock for useUserData
    mockedUseUserData.mockReturnValue({
      watchedItems: mockWatchedItems,
      shoppingLists: [],
      setWatchedItems: vi.fn(),
      setShoppingLists: vi.fn(),
      isLoading: false,
      error: null,
    });
  });

  it('should render a placeholder when there are no watched items', () => {
    mockedUseUserData.mockReturnValue({
      watchedItems: [],
      shoppingLists: [],
      setWatchedItems: vi.fn(),
      setShoppingLists: vi.fn(),
      isLoading: false,
      error: null,
    });
    render(<PriceHistoryChart />);
    expect(screen.getByText('Add items to your watchlist to see their price trends over time.')).toBeInTheDocument();
  });

  it('should display a loading state while fetching data', () => {
    vi.mocked(apiClient.fetchHistoricalPriceData).mockReturnValue(new Promise(() => {}));
    render(<PriceHistoryChart />);
    expect(screen.getByText('Loading Price History...')).toBeInTheDocument();
  });

  it('should display an error message if the API call fails', async () => {
    vi.mocked(apiClient.fetchHistoricalPriceData).mockRejectedValue(new Error('API is down'));
    render(<PriceHistoryChart />);

    await waitFor(() => {
      // Use regex to match the error message text which might be split across elements
      expect(screen.getByText(/API is down/)).toBeInTheDocument();
    });
  });

  it('should display a message if no historical data is returned', async () => {
    vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify([])));
    render(<PriceHistoryChart />);

    await waitFor(() => {
      expect(screen.getByText('Not enough historical data for your watched items. Process more flyers to build a trend.')).toBeInTheDocument();
    });
  });

  it('should render the chart with data on successful fetch', async () => {
    vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(mockPriceHistory)));
    render(<PriceHistoryChart />);

    await waitFor(() => {
      // Check that the API was called with the correct item IDs
      expect(apiClient.fetchHistoricalPriceData).toHaveBeenCalledWith([1, 2]);

      // Check that the chart components are rendered
      expect(screen.getByTestId('responsive-container')).toBeInTheDocument();
      expect(screen.getByTestId('line-chart')).toBeInTheDocument();
      expect(screen.getByTestId('x-axis')).toBeInTheDocument();
      expect(screen.getByTestId('y-axis')).toBeInTheDocument();
      expect(screen.getByTestId('legend')).toBeInTheDocument();

      // Check that a line is rendered for each watched item
      expect(screen.getByTestId('line-Organic Bananas')).toBeInTheDocument();
      expect(screen.getByTestId('line-Almond Milk')).toBeInTheDocument();
    });
  });
});