/**
 * BooleanField Tests
 *
 * Tests the boolean field component including:
 * - Basic rendering
 * - Checkbox toggle
 * - Value coercion
 * - Error display
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { BooleanField } from './BooleanField';
import { ActionField } from '../../types/action';

// Mock Checkbox component
vi.mock('../ui/checkbox', () => ({
  Checkbox: ({
    id,
    checked,
    onCheckedChange,
    className,
  }: {
    id: string;
    checked: boolean;
    onCheckedChange: (checked: boolean) => void;
    className?: string;
  }) => (
    <input
      type="checkbox"
      id={id}
      checked={checked}
      onChange={(e) => onCheckedChange(e.target.checked)}
      data-testid="checkbox"
      className={className}
    />
  ),
}));

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

  const defaultField: ActionField = {
    label: 'Enable Feature',
    type: 'boolean',
    description: 'Enable this feature for the workflow',
    required: false,
  };

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

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

  describe('basic rendering', () => {
    it('renders the field label', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByText('Enable Feature')).toBeInTheDocument();
    });

    it('renders checkbox', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).toBeInTheDocument();
    });

    it('renders description as checkbox label', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByText('Enable this feature for the workflow')).toBeInTheDocument();
    });

    it('sets correct checkbox id', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).toHaveAttribute('id', 'enabled');
    });
  });

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

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

      render(
        <BooleanField
          fieldName="enabled"
          field={requiredField}
          value={false}
          onChange={mockOnChange}
        />,
      );

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

    it('does not show asterisk when field is not required', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

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

  // ==========================================================================
  // Checkbox State Tests
  // ==========================================================================

  describe('checkbox state', () => {
    it('shows checked when value is true', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={true}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).toBeChecked();
    });

    it('shows unchecked when value is false', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).not.toBeChecked();
    });

    it('coerces truthy values to true', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={1 as any}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).toBeChecked();
    });

    it('coerces falsy values to false', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={0 as any}
          onChange={mockOnChange}
        />,
      );

      expect(screen.getByTestId('checkbox')).not.toBeChecked();
    });
  });

  // ==========================================================================
  // Toggle Tests
  // ==========================================================================

  describe('toggle', () => {
    it('calls onChange with true when checking', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      fireEvent.click(screen.getByTestId('checkbox'));

      expect(mockOnChange).toHaveBeenCalledWith(true);
    });

    it('calls onChange with false when unchecking', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={true}
          onChange={mockOnChange}
        />,
      );

      fireEvent.click(screen.getByTestId('checkbox'));

      expect(mockOnChange).toHaveBeenCalledWith(false);
    });
  });

  // ==========================================================================
  // Label Click Tests
  // ==========================================================================

  describe('label interaction', () => {
    it('has clickable description label', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      const label = screen.getByText('Enable this feature for the workflow');
      expect(label).toHaveClass('cursor-pointer');
    });

    it('label has htmlFor matching checkbox id', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

      const label = screen.getByText('Enable this feature for the workflow');
      expect(label).toHaveAttribute('for', 'enabled');
    });
  });

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

  describe('error display', () => {
    it('displays error message when provided', () => {
      render(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
          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(
        <BooleanField
          fieldName="enabled"
          field={defaultField}
          value={false}
          onChange={mockOnChange}
        />,
      );

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