import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';

import type { ActiveJob } from '@/types';

import GlobalJobNotifications from './GlobalJobNotifications';

// Mock Inertia Link component
vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Link: ({
      href,
      children,
      className,
    }: {
      href: string;
      children: React.ReactNode;
      className?: string;
    }) => (
      <a href={href} className={className}>
        {children}
      </a>
    ),
  };
});

describe('GlobalJobNotifications', () => {
  it('returns null when jobs array is empty', () => {
    const { container } = render(<GlobalJobNotifications jobs={[]} />);
    expect(container.firstChild).toBeNull();
  });

  it('renders container with correct accessibility attributes', () => {
    const jobs: ActiveJob[] = [
      {
        id: 1,
        type: 'analysis',
        site_id: 1,
        site_name: 'Example Site',
        status: 'processing',
        progress_percent: 0,
        completed: 0,
        total: 0,
        estimated_seconds_remaining: null,
      },
    ];

    render(<GlobalJobNotifications jobs={jobs} />);

    const container = screen.getByRole('status');
    expect(container).toHaveAttribute('aria-live', 'polite');
    expect(container).toHaveAttribute('aria-label', 'Active background jobs');
  });

  describe('AI draft jobs', () => {
    it('renders pending AI draft job with correct label and icon', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 5,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText('Example Site:')).toBeInTheDocument();
      expect(screen.getByText('Drafts queued (0/5)')).toBeInTheDocument();
    });

    it('renders processing AI draft job with correct label', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 40,
          completed: 2,
          total: 5,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText('Generating drafts (2/5)')).toBeInTheDocument();
    });

    it('renders AI draft job without progress when total is 0', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText('Drafts queued')).toBeInTheDocument();
    });

    it('renders progress bar for AI draft job when progress_percent > 0', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 60,
          completed: 3,
          total: 5,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const progressBar = container.querySelector('[style*="width: 60%"]');
      expect(progressBar).toBeInTheDocument();
    });

    it('does not render progress bar when progress_percent is 0', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 5,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const progressBar = container.querySelector('[style*="width:"]');
      expect(progressBar).not.toBeInTheDocument();
    });

    it('generates correct link for AI draft job', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 123,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 50,
          completed: 2,
          total: 4,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      const link = screen.getByRole('link');
      expect(link).toHaveAttribute('href', '/sites/123/recommendations');
    });
  });

  describe('Analysis jobs', () => {
    it('renders pending analysis job with correct label', () => {
      const jobs: ActiveJob[] = [
        {
          id: 2,
          type: 'analysis',
          site_id: 2,
          site_name: 'My Blog',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText('My Blog:')).toBeInTheDocument();
      expect(screen.getByText('Analysis queued')).toBeInTheDocument();
    });

    it('renders processing analysis job with correct label', () => {
      const jobs: ActiveJob[] = [
        {
          id: 2,
          type: 'analysis',
          site_id: 2,
          site_name: 'My Blog',
          status: 'processing',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText(/comparing traffic patterns/i)).toBeInTheDocument();
    });

    it('generates correct link for analysis job', () => {
      const jobs: ActiveJob[] = [
        {
          id: 2,
          type: 'analysis',
          site_id: 456,
          site_name: 'My Blog',
          status: 'processing',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      const link = screen.getByRole('link');
      expect(link).toHaveAttribute('href', '/sites/456/analyze');
    });
  });

  describe('Multiple jobs', () => {
    it('renders multiple jobs correctly', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Site One',
          status: 'processing',
          progress_percent: 50,
          completed: 2,
          total: 4,
          estimated_seconds_remaining: null,
        },
        {
          id: 2,
          type: 'analysis',
          site_id: 2,
          site_name: 'Site Two',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
        {
          id: 3,
          type: 'ai_draft',
          site_id: 3,
          site_name: 'Site Three',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 3,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      expect(screen.getByText('Site One:')).toBeInTheDocument();
      expect(screen.getByText('Generating drafts (2/4)')).toBeInTheDocument();

      expect(screen.getByText('Site Two:')).toBeInTheDocument();
      expect(screen.getByText('Analysis queued')).toBeInTheDocument();

      expect(screen.getByText('Site Three:')).toBeInTheDocument();
      expect(screen.getByText('Drafts queued (0/3)')).toBeInTheDocument();

      const links = screen.getAllByRole('link');
      expect(links).toHaveLength(3);
    });

    it('generates unique keys for each job', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Site One',
          status: 'processing',
          progress_percent: 50,
          completed: 2,
          total: 4,
          estimated_seconds_remaining: null,
        },
        {
          id: 1,
          type: 'analysis',
          site_id: 1,
          site_name: 'Site One',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const links = container.querySelectorAll('a');
      expect(links).toHaveLength(2);
    });
  });

  describe('Icon rendering', () => {
    it('renders Bot icon for pending AI draft job', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      // The Bot icon should be rendered with aria-hidden="true"
      const icon = container.querySelector('svg[aria-hidden="true"]');
      expect(icon).toBeInTheDocument();
      expect(icon?.classList.toString()).toContain('text-warning');
    });

    it('renders Search icon for pending analysis job', () => {
      const jobs: ActiveJob[] = [
        {
          id: 2,
          type: 'analysis',
          site_id: 2,
          site_name: 'Example Site',
          status: 'pending',
          progress_percent: 0,
          completed: 0,
          total: 0,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const icon = container.querySelector('svg[aria-hidden="true"]');
      expect(icon).toBeInTheDocument();
      expect(icon?.classList.toString()).toContain('text-warning');
    });

    it('renders Loader2 icon with spin animation for processing jobs', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 50,
          completed: 2,
          total: 4,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const icon = container.querySelector('svg[aria-hidden="true"]');
      expect(icon).toBeInTheDocument();
      expect(icon?.classList.toString()).toContain('text-blue-600');
      expect(icon?.classList.toString()).toContain('animate-spin');
    });
  });

  describe('Accessibility', () => {
    it('marks icons as decorative with aria-hidden', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 50,
          completed: 2,
          total: 4,
          estimated_seconds_remaining: null,
        },
      ];

      const { container } = render(<GlobalJobNotifications jobs={jobs} />);

      const icons = container.querySelectorAll('svg[aria-hidden="true"]');
      // Should have both the job icon and the progress bar container (which also has aria-hidden)
      expect(icons.length).toBeGreaterThan(0);
    });

    it('marks progress bar with progressbar role and aria values', () => {
      const jobs: ActiveJob[] = [
        {
          id: 1,
          type: 'ai_draft',
          site_id: 1,
          site_name: 'Example Site',
          status: 'processing',
          progress_percent: 75,
          completed: 3,
          total: 4,
          estimated_seconds_remaining: null,
        },
      ];

      render(<GlobalJobNotifications jobs={jobs} />);

      const progressBar = screen.getByRole('progressbar');
      expect(progressBar).toHaveAttribute('aria-valuenow', '75');
      expect(progressBar).toHaveAttribute('aria-valuemin', '0');
      expect(progressBar).toHaveAttribute('aria-valuemax', '100');
      expect(progressBar).toHaveAttribute('aria-label', '75% complete');
    });
  });
});
