// src/features/flyer/ProcessingStatus.test.tsx
import React from 'react';
import { render, screen, act } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { ProcessingStatus } from './ProcessingStatus';
import type { ProcessingStage } from '../../types';

describe('ProcessingStatus', () => {
  const mockStages: ProcessingStage[] = [
    { name: 'Uploading File', status: 'completed', detail: 'Done' },
    { name: 'Converting to Image', status: 'in-progress', detail: 'Page 2 of 5...' },
    { name: 'Extracting Text', status: 'pending', detail: '' },
    { name: 'Analyzing with AI', status: 'error', detail: 'AI model timeout', critical: false },
    { name: 'Saving to Database', status: 'error', detail: 'Connection failed', critical: true },
  ];

  describe('Single File Layout', () => {
    it('should render the title and initial time remaining', () => {
      render(<ProcessingStatus stages={[]} estimatedTime={125} />);
      expect(screen.getByRole('heading', { name: /processing your flyer/i })).toBeInTheDocument();
      expect(screen.getByText(/estimated time remaining: 2m 5s/i)).toBeInTheDocument();
    });

    describe('with fake timers', () => {
      beforeEach(() => {
        vi.useFakeTimers();
      });

      afterEach(() => {
        vi.useRealTimers();
      });

      it('should count down the time remaining', () => {
        render(<ProcessingStatus stages={[]} estimatedTime={125} />);
        expect(screen.getByText(/estimated time remaining: 2m 5s/i)).toBeInTheDocument();
  
        act(() => {
          vi.advanceTimersByTime(3000); // Advance time by 3 seconds
        });
  
        expect(screen.getByText(/estimated time remaining: 2m 2s/i)).toBeInTheDocument();
      });
    })

    it('should render all stages with correct statuses and icons', () => {
      render(<ProcessingStatus stages={mockStages} estimatedTime={120} />);

      // Completed stage
      const completedStageText = screen.getByTestId('stage-text-0');
      expect(completedStageText.className).toContain('text-gray-700');
      expect(screen.getByTestId('stage-icon-0').querySelector('svg')).toHaveClass('text-green-500');

      // In-progress stage`
      const inProgressStageText = screen.getByTestId('stage-text-1');
      expect(inProgressStageText.className).toContain('text-brand-primary');
      expect(screen.getByTestId('stage-icon-1').querySelector('svg')).toHaveClass('animate-spin');

      // Pending stage
      const pendingStageText = screen.getByTestId('stage-text-2');
      expect(pendingStageText.className).toContain('text-gray-400');
      expect(screen.getByTestId('stage-icon-2').querySelector('div')).toHaveClass('border-gray-400');

      // Non-critical error stage
      const nonCriticalErrorStageText = screen.getByTestId('stage-text-3');
      expect(nonCriticalErrorStageText.className).toContain('text-yellow-600');
      expect(screen.getByTestId('stage-icon-3').querySelector('svg')).toHaveClass('text-yellow-500');
      expect(screen.getByText(/optional/i)).toBeInTheDocument();

      // Critical error stage
      const criticalErrorStageText = screen.getByTestId('stage-text-4');
      expect(criticalErrorStageText.className).toContain('text-red-500');
      expect(screen.getByTestId('stage-icon-4').querySelector('svg')).toHaveClass('text-red-500');
    });

    it('should render PDF conversion progress bar', () => {
      render(<ProcessingStatus stages={[]} estimatedTime={60} pageProgress={{ current: 3, total: 10 }} />);
      const progressBar = screen.getByText(/converting pdf: page 3 of 10/i).nextElementSibling?.firstChild;
      expect(progressBar).toBeInTheDocument();
      expect(progressBar).toHaveStyle('width: 30%');
    });

    it('should render item extraction progress bar for a stage', () => {
      const stagesWithProgress: ProcessingStage[] = [
        { name: 'Extracting Items', status: 'in-progress', progress: { current: 4, total: 8 } },
      ];
      render(<ProcessingStatus stages={stagesWithProgress} estimatedTime={60} />);
      const progressBar = screen.getByText(/analyzing page 4 of 8/i).nextElementSibling?.firstChild;
      expect(progressBar).toBeInTheDocument();
      expect(progressBar).toHaveStyle('width: 50%');
    });
  });

  describe('Bulk Processing Layout', () => {
    const bulkProps = {
      stages: mockStages,
      estimatedTime: 300,
      currentFile: 'flyer_batch_01.pdf',
      bulkProgress: 25,
      bulkFileCount: { current: 2, total: 8 },
    };

    it('should render the bulk processing layout with current file name', () => {
      render(<ProcessingStatus {...bulkProps} />);
      // The heading now includes the filename, so we can check for it in one assertion.
      const heading = screen.getByRole('heading', { name: /Processing: flyer_batch_01.pdf/i });
      expect(heading).toBeInTheDocument();
    });

    it('should render the overall bulk progress bar', () => {
      render(<ProcessingStatus {...bulkProps} />);
      const progressBar = screen.getByText(/file 2 of 8/i).nextElementSibling?.firstChild;
      expect(progressBar).toBeInTheDocument();
      expect(progressBar).toHaveStyle('width: 25%');
    });

    it('should render the PDF conversion progress bar in bulk mode', () => {
      render(<ProcessingStatus {...bulkProps} pageProgress={{ current: 1, total: 5 }} />);
      const progressBar = screen.getByText(/converting pdf: page 1 of 5/i).nextElementSibling?.firstChild;
      expect(progressBar).toBeInTheDocument();
      expect(progressBar).toHaveStyle('width: 20%');
    });

    it('should render the item extraction progress bar from the correct stage in bulk mode', () => {
      const stagesWithProgress: ProcessingStage[] = [
        { name: 'Some Other Step', status: 'completed' },
        { name: 'Extracting All Items from Flyer', status: 'in-progress', progress: { current: 3, total: 10 } },
      ];
      render(<ProcessingStatus {...bulkProps} stages={stagesWithProgress} />);
      const progressBar = screen.getByText(/analyzing page 3 of 10/i).nextElementSibling?.firstChild;
      expect(progressBar).toBeInTheDocument();
      expect(progressBar).toHaveStyle('width: 30%');
    });

    it('should render the checklist of stages on the right', () => {
      render(<ProcessingStatus {...bulkProps} />);
      // Find the list of stages by its role. This is more robust than relying on specific CSS classes.
      const stageList = screen.getByRole('list');
      expect(stageList).toBeInTheDocument();
      expect(stageList).toHaveTextContent('Uploading File');
      expect(stageList).toHaveTextContent('Converting to Image');
    });
  });
});