/**
 * Tests for Connection Status component validation enhancement (Story 4.2)
 *
 * Tests the enhanced component with detailed error display.
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { ConnectionStatus } from './connection-status';
import { ApiErrorType } from '@/types/settings';
import { useApiKey } from '@/store/use-settings';

// Mock the settings service
vi.mock('@/services/settings-service', () => ({
  SettingsService: {
    validateProviderConnection: vi.fn(),
  },
}));

// Mock the settings store
vi.mock('@/store/use-settings', () => ({
  useApiKey: vi.fn(() => 'sk-test-key'),
}));

import { SettingsService } from '@/services/settings-service';

describe('ConnectionStatus Component - Validation Enhancement (Story 4.2)', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should display success status when connection is valid', async () => {
    vi.mocked(SettingsService.validateProviderConnection).mockResolvedValueOnce({
      isValid: true,
    });

    render(<ConnectionStatus />);

    const testButton = screen.getByRole('button', { name: /test connection/i });
    testButton.click();

    await waitFor(() => {
      expect(screen.getByText(/connected/i)).toBeInTheDocument();
    });
  });

  it('should display detailed error message for invalid API key', async () => {
    vi.mocked(SettingsService.validateProviderConnection).mockResolvedValueOnce({
      isValid: false,
      error: 'Your API key appears to be invalid or expired.',
    });

    render(<ConnectionStatus />);

    const testButton = screen.getByRole('button', { name: /test connection/i });
    testButton.click();

    await waitFor(() => {
      expect(screen.getByText(/connection failed/i)).toBeInTheDocument();
      expect(screen.getByText(/invalid or expired/i)).toBeInTheDocument();
    });
  });

  it('should show loading state during validation', async () => {
    // Make validation take some time
    vi.mocked(SettingsService.validateProviderConnection).mockImplementationOnce(
      () => new Promise((resolve) => setTimeout(() => resolve({ isValid: true }), 100))
    );

    render(<ConnectionStatus />);

    const testButton = screen.getByRole('button', { name: /test connection/i });
    testButton.click();

    // The button text should change to "Testing..." during validation
    await waitFor(() => {
      expect(screen.getByRole('button', { name: /testing/i })).toBeInTheDocument();
    });

    await waitFor(() => {
      expect(screen.getByText(/connected/i)).toBeInTheDocument();
    });
  });

  it('should disable button while testing', async () => {
    vi.mocked(SettingsService.validateProviderConnection).mockImplementationOnce(
      () => new Promise((resolve) => setTimeout(() => resolve({ isValid: true }), 100))
    );

    render(<ConnectionStatus />);

    const testButton = screen.getByRole('button', { name: /test connection/i });
    testButton.click();

    // Check that button is disabled during testing
    await waitFor(() => {
      expect(testButton).toBeDisabled();
    });

    await waitFor(() => {
      expect(testButton).not.toBeDisabled();
    });
  });

  it('should not render when API key is not present', () => {
    vi.mocked(useApiKey).mockReturnValueOnce('');

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

    expect(container.firstChild).toBeNull();
  });

  it('should enable retry after failed connection', async () => {
    vi.mocked(SettingsService.validateProviderConnection)
      .mockResolvedValueOnce({
        isValid: false,
        error: 'Network error',
      })
      .mockResolvedValueOnce({
        isValid: true,
      });

    render(<ConnectionStatus />);

    const testButton = screen.getByRole('button', { name: /test connection/i });

    // First attempt - fails
    testButton.click();
    await waitFor(() => {
      expect(screen.getByText(/connection failed/i)).toBeInTheDocument();
    });

    // Second attempt - succeeds
    testButton.click();
    await waitFor(() => {
      expect(screen.getByText(/connected/i)).toBeInTheDocument();
    });
  });
});
