/**
 * HistoryFeed Component Tests
 * Story 3.1: Testing history feed with lazy loading
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { HistoryFeed } from './HistoryFeed';
import { useHistoryStore } from '@/lib/store/history-store';
import { DraftService } from '@/lib/db/draft-service';

// Mock HistoryStore
vi.mock('@/lib/store/history-store', () => ({
  useHistoryStore: vi.fn()
}));

// Mock DraftService
vi.mock('@/lib/db/draft-service', () => ({
  DraftService: {
    getCompletedDrafts: vi.fn()
  }
}));

const mockDraft = {
  id: 1,
  sessionId: 'test-session',
  title: 'Test Draft',
  content: 'Test content',
  tags: ['test'],
  createdAt: Date.now(),
  completedAt: Date.now(),
  status: 'completed' as const
};

describe('HistoryFeed', () => {
  const mockLoadMore = vi.fn();
  const mockClearError = vi.fn();
  const mockRefreshHistory = vi.fn();
  const mockSelectDraft = vi.fn();
  const mockCloseDetail = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();

    // Default mock store state
    vi.mocked(useHistoryStore).mockImplementation((selector) => {
      const state = {
        drafts: [],
        loading: false,
        hasMore: true,
        error: null,
        loadMore: mockLoadMore,
        clearError: mockClearError,
        refreshHistory: mockRefreshHistory,
        selectDraft: mockSelectDraft,
        closeDetail: mockCloseDetail,
        selectedDraft: null
      };

      return selector ? selector(state) : state;
    });
  });

  describe('initial loading', () => {
    it('shows loading spinner on initial load', () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [],
          loading: true,
          hasMore: true,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      expect(screen.getByText(/Loading more entries/i)).toBeInTheDocument();
    });

    it('calls loadMore on mount', () => {
      render(<HistoryFeed />);

      expect(mockLoadMore).toHaveBeenCalled();
    });
  });

  describe('empty state', () => {
    it('shows empty state when no drafts', async () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [],
          loading: false,
          hasMore: true,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      await waitFor(() => {
        expect(screen.getByText('Your journey starts here')).toBeInTheDocument();
      });
    });

    it('shows CTA button in empty state', async () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [],
          loading: false,
          hasMore: true,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      await waitFor(() => {
        expect(screen.getByText('Start My First Vent')).toBeInTheDocument();
      });
    });
  });

  describe('rendering drafts', () => {
    it('renders draft cards', () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [mockDraft],
          loading: false,
          hasMore: true,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      expect(screen.getByText('Test Draft')).toBeInTheDocument();
    });

    it('shows loading indicator when loading more', () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [mockDraft],
          loading: true,
          hasMore: true,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      expect(screen.getByText(/Loading more entries/i)).toBeInTheDocument();
    });
  });

  describe('error state', () => {
    it('shows error message and retry button', () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [],
          loading: false,
          hasMore: true,
          error: 'Failed to load history',
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      expect(screen.getByText('Failed to load history')).toBeInTheDocument();
      expect(screen.getByText('Retry')).toBeInTheDocument();
    });

    it('clears error and retries when retry clicked', async () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [],
          loading: false,
          hasMore: true,
          error: 'Failed to load history',
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      const user = userEvent.setup();

      render(<HistoryFeed />);

      const retryButton = screen.getByText('Retry');
      await user.click(retryButton);

      expect(mockClearError).toHaveBeenCalled();
      expect(mockLoadMore).toHaveBeenCalled();
    });
  });

  describe('end of list', () => {
    it('shows end message when no more drafts', () => {
      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: [mockDraft],
          loading: false,
          hasMore: false,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      expect(screen.getByText("You've reached the beginning")).toBeInTheDocument();
    });
  });

  describe('week-based grouping', () => {
    it('groups drafts by week with headers', () => {
      const now = new Date('2026-01-25T10:00:00');
      const lastWeek = new Date('2026-01-18T10:00:00');

      const draftsFromDifferentWeeks = [
        { ...mockDraft, id: 1, title: 'Draft 1', createdAt: now.getTime() },
        { ...mockDraft, id: 2, title: 'Draft 2', createdAt: now.getTime() },
        { ...mockDraft, id: 3, title: 'Draft 3', createdAt: lastWeek.getTime() },
      ];

      vi.mocked(useHistoryStore).mockImplementation((selector) => {
        const state = {
          drafts: draftsFromDifferentWeeks,
          loading: false,
          hasMore: false,
          error: null,
          loadMore: mockLoadMore,
          clearError: mockClearError,
          refreshHistory: mockRefreshHistory,
          selectDraft: mockSelectDraft,
          closeDetail: mockCloseDetail,
          selectedDraft: null
        };

        return selector ? selector(state) : state;
      });

      render(<HistoryFeed />);

      // Should show week headers (W4 - 2026 and W3 - 2026)
      expect(screen.getByText(/W4 - 2026/)).toBeInTheDocument();
      expect(screen.getByText(/W3 - 2026/)).toBeInTheDocument();

      // Should show all drafts
      expect(screen.getByText('Draft 1')).toBeInTheDocument();
      expect(screen.getByText('Draft 2')).toBeInTheDocument();
      expect(screen.getByText('Draft 3')).toBeInTheDocument();
    });
  });
});
