/**
 * DynamicSelectField Tests
 *
 * Tests the dynamic select field component including:
 * - Basic rendering
 * - Loading state
 * - Dependency handling
 * - Option display
 * - Error states
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { DynamicSelectField } from './DynamicSelectField';
import { ActionField } from '../../types/action';

// Mock Select components
vi.mock('../ui/select', () => ({
  Select: ({
    value,
    onValueChange,
    disabled,
    children,
  }: {
    value: string;
    onValueChange: (v: string) => void;
    disabled?: boolean;
    children: React.ReactNode;
  }) => (
    <div
      data-testid="select-root"
      data-value={value}
      data-disabled={disabled}
      onClick={() => !disabled && onValueChange('test-value')}
    >
      {children}
    </div>
  ),
  SelectTrigger: ({ id, children }: { id: string; children: React.ReactNode }) => (
    <button data-testid="select-trigger" id={id}>
      {children}
    </button>
  ),
  SelectValue: ({ placeholder }: { placeholder?: string }) => (
    <span data-testid="select-value">{placeholder}</span>
  ),
  SelectContent: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="select-content">{children}</div>
  ),
  SelectItem: ({ value, children }: { value: string; children: React.ReactNode }) => (
    <div data-testid={`select-item-${value}`} data-value={value}>
      {children}
    </div>
  ),
}));

describe('DynamicSelectField', () => {
  const mockOnChange = vi.fn();

  const defaultField: ActionField = {
    label: 'Mailing List',
    type: 'select',
    description: 'Select a mailing list',
    required: false,
    dynamic: true,
  };

  const defaultOptions = [
    { value: 'list-1', label: 'Newsletter' },
    { value: 'list-2', label: 'Updates' },
    { value: 'list-3', label: 'Promotions' },
  ];

  const defaultProps = {
    fieldName: 'list_id',
    field: defaultField,
    value: '',
    options: defaultOptions,
    isLoading: false,
    onChange: mockOnChange,
    dependencyMet: true,
  };

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

  // ==========================================================================
  // Basic Rendering Tests
  // ==========================================================================

  describe('basic rendering', () => {
    it('renders the field label', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByText('Mailing List')).toBeInTheDocument();
    });

    it('renders description', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByText('Select a mailing list')).toBeInTheDocument();
    });

    it('renders select when loaded and dependency met', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByTestId('select-root')).toBeInTheDocument();
    });

    it('shows required asterisk when field is required', () => {
      const requiredField = { ...defaultField, required: true };

      render(<DynamicSelectField {...defaultProps} field={requiredField} />);

      expect(screen.getByText('*')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Loading State Tests
  // ==========================================================================

  describe('loading state', () => {
    it('shows loading indicator when isLoading is true', () => {
      render(<DynamicSelectField {...defaultProps} isLoading={true} />);

      expect(screen.getByText('Loading options...')).toBeInTheDocument();
    });

    it('does not show select when loading', () => {
      render(<DynamicSelectField {...defaultProps} isLoading={true} />);

      expect(screen.queryByTestId('select-root')).not.toBeInTheDocument();
    });

    it('shows loading only when dependency is met', () => {
      render(<DynamicSelectField {...defaultProps} isLoading={true} dependencyMet={false} />);

      // Should show dependency message, not loading
      expect(screen.queryByText('Loading options...')).not.toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Dependency Not Met Tests
  // ==========================================================================

  describe('dependency not met', () => {
    it('shows dependency message when dependency not met', () => {
      const fieldWithDependency = {
        ...defaultField,
        depends_on: 'workspace_id',
      };

      render(
        <DynamicSelectField {...defaultProps} field={fieldWithDependency} dependencyMet={false} />,
      );

      expect(screen.getByText(/Select a workspace/)).toBeInTheDocument();
    });

    it('uses custom dependency label when provided', () => {
      render(
        <DynamicSelectField {...defaultProps} dependencyMet={false} dependencyLabel="workspace" />,
      );

      expect(screen.getByText('Select a workspace first.')).toBeInTheDocument();
    });

    it('formats depends_on field name in message', () => {
      const fieldWithDependency = {
        ...defaultField,
        depends_on: 'workspace_id',
      };

      render(
        <DynamicSelectField {...defaultProps} field={fieldWithDependency} dependencyMet={false} />,
      );

      expect(screen.getByText('Select a workspace id first.')).toBeInTheDocument();
    });

    it('does not show select when dependency not met', () => {
      render(<DynamicSelectField {...defaultProps} dependencyMet={false} />);

      expect(screen.queryByTestId('select-root')).not.toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Field Error Tests
  // ==========================================================================

  describe('field error', () => {
    it('shows field error message', () => {
      render(<DynamicSelectField {...defaultProps} fieldError="Failed to load options" />);

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

    it('does not show select when field has error', () => {
      render(<DynamicSelectField {...defaultProps} fieldError="Failed to load options" />);

      expect(screen.queryByTestId('select-root')).not.toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Options Tests
  // ==========================================================================

  describe('options', () => {
    it('renders all options', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByTestId('select-item-list-1')).toBeInTheDocument();
      expect(screen.getByTestId('select-item-list-2')).toBeInTheDocument();
      expect(screen.getByTestId('select-item-list-3')).toBeInTheDocument();
    });

    it('displays option labels', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByText('Newsletter')).toBeInTheDocument();
      expect(screen.getByText('Updates')).toBeInTheDocument();
      expect(screen.getByText('Promotions')).toBeInTheDocument();
    });

    it('shows no options message when options empty', () => {
      render(<DynamicSelectField {...defaultProps} options={[]} />);

      expect(screen.getByText(/No mailing list available/i)).toBeInTheDocument();
    });

    it('disables select when no options', () => {
      render(<DynamicSelectField {...defaultProps} options={[]} />);

      expect(screen.getByTestId('select-root')).toHaveAttribute('data-disabled', 'true');
    });
  });

  // ==========================================================================
  // Value Tests
  // ==========================================================================

  describe('value handling', () => {
    it('passes current value to select', () => {
      render(<DynamicSelectField {...defaultProps} value="list-2" />);

      expect(screen.getByTestId('select-root')).toHaveAttribute('data-value', 'list-2');
    });

    it('calls onChange when value changes', () => {
      render(<DynamicSelectField {...defaultProps} />);

      fireEvent.click(screen.getByTestId('select-root'));

      expect(mockOnChange).toHaveBeenCalledWith('test-value');
    });
  });

  // ==========================================================================
  // Validation Error Tests
  // ==========================================================================

  describe('validation error', () => {
    it('displays validation error', () => {
      render(<DynamicSelectField {...defaultProps} error="Please select a list" />);

      expect(screen.getByText('Please select a list')).toBeInTheDocument();
    });

    it('shows both field error and validation error', () => {
      render(
        <DynamicSelectField {...defaultProps} fieldError="API error" error="Validation error" />,
      );

      // When there's a field error, select is hidden, so validation error shows separately
      expect(screen.getByText('API error')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Placeholder Tests
  // ==========================================================================

  describe('placeholder', () => {
    it('shows select placeholder with field label', () => {
      render(<DynamicSelectField {...defaultProps} />);

      expect(screen.getByTestId('select-value')).toHaveTextContent(/Select mailing list/i);
    });

    it('shows no options placeholder when empty', () => {
      render(<DynamicSelectField {...defaultProps} options={[]} />);

      expect(screen.getByTestId('select-value')).toHaveTextContent(/No mailing list available/i);
    });
  });
});
