/**
 * Tests for Provider Form component validation enhancement (Story 4.2)
 *
 * Tests the debounced validation, visual indicators, and save integration.
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ProviderForm } from './provider-form';

// Create stable mock functions
const mockActions = {
  setApiKey: vi.fn(),
  setBaseUrl: vi.fn(),
  setModelName: vi.fn(),
  clearSettings: vi.fn(),
};

// Mock the settings store with stable references
vi.mock('@/store/use-settings', () => ({
  useApiKey: vi.fn(() => 'sk-test-key'),
  useBaseUrl: vi.fn(() => 'https://api.openai.com/v1'),
  useModelName: vi.fn(() => 'gpt-4o'),
  useSettingsActions: vi.fn(() => mockActions),
}));

// Mock the connection status component
vi.mock('./connection-status', () => ({
  ConnectionStatus: vi.fn(() => <div data-testid="connection-status" />),
}));

// Mock SettingsService to avoid real API calls
vi.mock('@/services/settings-service', () => ({
  SettingsService: {
    saveProviderSettingsWithValidation: vi.fn(),
  },
}));

// Mock toast
vi.mock('@/hooks/use-toast', () => ({
  toast: vi.fn(),
}));

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

  it('should render all form fields with correct labels', () => {
    render(<ProviderForm />);

    expect(screen.getByLabelText(/base url/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/model name/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/^api key$/i)).toBeInTheDocument();
  });

  it('should update values when user types', async () => {
    render(<ProviderForm />);

    const urlInput = screen.getByLabelText(/base url/i);
    const modelInput = screen.getByLabelText(/model name/i);
    const keyInput = screen.getByLabelText(/^api key$/i);

    await userEvent.clear(urlInput);
    await userEvent.type(urlInput, 'https://api.custom.com/v1');
    await userEvent.clear(modelInput);
    await userEvent.type(modelInput, 'custom-model');
    await userEvent.clear(keyInput);
    await userEvent.type(keyInput, 'sk-custom-key');

    // Verify actions were called (form uses controlled inputs from store)
    expect(mockActions.setBaseUrl).toHaveBeenCalled();
    expect(mockActions.setModelName).toHaveBeenCalled();
    expect(mockActions.setApiKey).toHaveBeenCalled();
  });

  it('should show/hide API key when toggle is clicked', async () => {
    render(<ProviderForm />);

    const keyInput = screen.getByLabelText(/^api key$/i) as HTMLInputElement;
    const toggleButton = screen.getByRole('button', { name: /show/i });

    // Initially password type
    expect(keyInput.type).toBe('password');

    await userEvent.click(toggleButton);

    // Now text type
    expect(keyInput.type).toBe('text');

    // Click again to hide
    const hideButton = screen.getByRole('button', { name: /hide/i });
    await userEvent.click(hideButton);

    expect(keyInput.type).toBe('password');
  });

  it('should display provider preset buttons', () => {
    render(<ProviderForm />);

    expect(screen.getByRole('button', { name: 'OpenAI' })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'DeepSeek' })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'OpenRouter' })).toBeInTheDocument();
  });

  it('should fill form when provider preset is selected', async () => {
    render(<ProviderForm />);

    const deepseekButton = screen.getByRole('button', { name: 'DeepSeek' });
    await userEvent.click(deepseekButton);

    // Verify preset selection calls the correct actions
    expect(mockActions.setBaseUrl).toHaveBeenCalledWith('https://api.deepseek.com/v1');
    expect(mockActions.setModelName).toHaveBeenCalledWith('deepseek-chat');
  });

  it('should display connection status component', () => {
    render(<ProviderForm />);

    expect(screen.getByTestId('connection-status')).toBeInTheDocument();
  });

  it('should show helper text for each field', () => {
    render(<ProviderForm />);

    expect(screen.getByText(/api endpoint url/i)).toBeInTheDocument();
    expect(screen.getByText(/model identifier/i)).toBeInTheDocument();
    // "stored locally" appears in both helper text and card description
    expect(screen.getAllByText(/stored locally/i).length).toBeGreaterThan(0);
  });

  it('should handle empty API key gracefully', () => {
    render(<ProviderForm />);

    // When API key is empty, ConnectionStatus should still render
    expect(screen.getByTestId('connection-status')).toBeInTheDocument();
  });
});
