/**
 * StringField Tests
 *
 * Tests the string field component including:
 * - Basic rendering
 * - Label and required indicator
 * - VariableInput integration
 * - Multiline mode
 * - Error display
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import { StringField } from './StringField';
import { ActionField } from '../../types/action';
import { AvailableContext } from '../../hooks/useAvailableContext';

// Mock VariableInput
vi.mock('../VariableInput', () => ({
  VariableInput: ({
    value,
    onChange,
    placeholder,
    multiline,
  }: {
    value: string;
    onChange: (v: string) => void;
    placeholder?: string;
    multiline?: boolean;
  }) => (
    <input
      data-testid="variable-input"
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      data-multiline={multiline}
    />
  ),
}));

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

  const defaultField: ActionField = {
    label: 'Email Address',
    type: 'string',
    description: 'Enter an email address',
    required: false,
  };

  const emptyContext: AvailableContext = {
    groups: [],
  };

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

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

  describe('basic rendering', () => {
    it('renders the field label', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByText('Email Address')).toBeInTheDocument();
    });

    it('renders VariableInput component', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toBeInTheDocument();
    });

    it('passes value to VariableInput', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value="test@example.com"
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toHaveValue('test@example.com');
    });
  });

  // ==========================================================================
  // Required Indicator Tests
  // ==========================================================================

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

      render(
        <StringField
          fieldName="email"
          field={requiredField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

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

    it('does not show asterisk when field is not required', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.queryByText('*')).not.toBeInTheDocument();
    });
  });

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

  describe('placeholder', () => {
    it('uses placeholder from field when provided', () => {
      const fieldWithPlaceholder = {
        ...defaultField,
        placeholder: 'Enter email here',
      };

      render(
        <StringField
          fieldName="email"
          field={fieldWithPlaceholder}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toHaveAttribute(
        'placeholder',
        'Enter email here',
      );
    });

    it('falls back to description when no placeholder', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toHaveAttribute(
        'placeholder',
        'Enter an email address',
      );
    });
  });

  // ==========================================================================
  // Multiline Mode Tests
  // ==========================================================================

  describe('multiline mode', () => {
    it('sets multiline=true for text type fields', () => {
      const textField: ActionField = { ...defaultField, type: 'text' };

      render(
        <StringField
          fieldName="body"
          field={textField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toHaveAttribute('data-multiline', 'true');
    });

    it('sets multiline=false for string type fields', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(screen.getByTestId('variable-input')).toHaveAttribute('data-multiline', 'false');
    });
  });

  // ==========================================================================
  // Error Display Tests
  // ==========================================================================

  describe('error display', () => {
    it('displays error message when provided', () => {
      render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
          error="This field is required"
        />,
      );

      expect(screen.getByText('This field is required')).toBeInTheDocument();
    });

    it('does not render error element when no error', () => {
      const { container } = render(
        <StringField
          fieldName="email"
          field={defaultField}
          value=""
          onChange={mockOnChange}
          availableContext={emptyContext}
        />,
      );

      expect(container.querySelector('.text-red-600')).not.toBeInTheDocument();
    });
  });
});
