/**
 * ActionConfigContent Tests
 *
 * Tests the action configuration content component including:
 * - Loading state
 * - Error state with retry
 * - No action state
 * - Empty schema state (no fields)
 * - Connection selector for integration actions
 * - Main fields rendering via SchemaFieldRenderer
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ActionConfigContent } from './ActionConfigContent';
import { Action, ActionField } from '../../types/action';
import { AvailableContext } from '../../types/workflow-context';

// Mock SchemaFieldRenderer with minimal stub
vi.mock('../fields/SchemaFieldRenderer', () => ({
  SchemaFieldRenderer: ({
    fieldName,
    field,
    value,
    onChange,
  }: {
    fieldName: string;
    field: { label?: string };
    value: unknown;
    onChange: (fieldName: string, value: unknown) => void;
  }) => (
    <div data-testid={`schema-field-${fieldName}`} data-value={String(value ?? '')}>
      <span data-testid={`field-label-${fieldName}`}>{field.label || fieldName}</span>
      <input
        data-testid={`input-${fieldName}`}
        value={String(value ?? '')}
        onChange={(e) => onChange(fieldName, e.target.value)}
      />
    </div>
  ),
}));

// Mock ConnectionSelector with minimal stub
vi.mock('./ConnectionSelector', () => ({
  ConnectionSelector: ({
    integration,
    value,
    onChange,
  }: {
    integration: string;
    value?: string;
    onChange: (id: string) => void;
  }) => (
    <div data-testid="connection-selector" data-integration={integration} data-value={value || ''}>
      <button data-testid="select-connection" onClick={() => onChange('conn-123')}>
        Select Connection
      </button>
    </div>
  ),
}));

// Test fixtures
const mockAction: Action = {
  type: 'wordpress/send_email',
  label: 'Send Email',
  description: 'Send an email notification',
  integration: 'wordpress',
  schema: {
    to: {
      type: 'string',
      label: 'To',
      description: 'Recipient',
      required: true,
    },
    subject: {
      type: 'string',
      label: 'Subject',
      description: 'Subject line',
      required: true,
    },
  },
  output_fields: [],
  is_available: true,
  availability_reason: '',
  is_connected: true,
  requires_connection: false,
};

const mockActionWithConnection: Action = {
  ...mockAction,
  type: 'mailchimp/add_subscriber',
  label: 'Add Subscriber',
  integration: 'mailchimp',
  requires_connection: true,
};

const mockMainFields: [string, ActionField][] = [
  [
    'to',
    {
      type: 'string',
      label: 'To',
      description: 'Recipient',
      required: true,
    },
  ],
  [
    'subject',
    {
      type: 'string',
      label: 'Subject',
      description: 'Subject line',
      required: true,
    },
  ],
];

const mockAvailableContext: AvailableContext = {
  groups: [
    {
      namespace: 'Trigger',
      sourceName: 'User Registration',
      sourceType: 'trigger',
      variables: [
        {
          path: 'Trigger.user_id',
          label: 'User ID',
          type: 'integer',
          source: 'User Registration',
          namespace: 'Trigger',
          description: 'The user ID',
          example: '123',
        },
        {
          path: 'Trigger.user_email',
          label: 'User email',
          type: 'string',
          source: 'User Registration',
          namespace: 'Trigger',
          description: 'The user email',
          example: 'test@example.com',
        },
      ],
    },
  ],
};

const defaultProps = {
  action: undefined as Action | undefined,
  isLoading: false,
  error: null as string | null,
  onRetry: vi.fn(),
  actionConfig: {} as Record<string, unknown>,
  onFieldChange: vi.fn(),
  availableContext: mockAvailableContext,
  mainFields: [] as [string, ActionField][],
  dynamicOptions: {} as Record<string, unknown[]>,
  loadingDynamicFields: {} as Record<string, boolean>,
  dynamicFieldErrors: {} as Record<string, string>,
  onQueueFetch: vi.fn(),
};

describe('ActionConfigContent', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('loading state', () => {
    it('renders loading spinner when isLoading is true', () => {
      const { container } = render(<ActionConfigContent {...defaultProps} isLoading={true} />);

      expect(container.querySelector('.animate-spin')).toBeInTheDocument();
    });

    it('shows loading text', () => {
      render(<ActionConfigContent {...defaultProps} isLoading={true} />);

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

    it('does not render action content when loading', () => {
      render(<ActionConfigContent {...defaultProps} isLoading={true} action={mockAction} />);

      expect(screen.queryByTestId('connection-selector')).not.toBeInTheDocument();
    });

    it('does not render schema fields when loading', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          isLoading={true}
          action={mockAction}
          mainFields={mockMainFields}
        />,
      );

      expect(screen.queryByTestId('schema-field-to')).not.toBeInTheDocument();
    });
  });

  describe('error state', () => {
    it('renders error message', () => {
      render(<ActionConfigContent {...defaultProps} error="Failed to load action" />);

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

    it('renders with error styling', () => {
      const { container } = render(<ActionConfigContent {...defaultProps} error="Error" />);

      expect(container.querySelector('.bg-rose-50')).toBeInTheDocument();
    });

    it('renders Retry button', () => {
      render(<ActionConfigContent {...defaultProps} error="Error" />);

      expect(screen.getByRole('button', { name: 'Retry' })).toBeInTheDocument();
    });

    it('calls onRetry when Retry button is clicked', async () => {
      const onRetry = vi.fn();
      render(<ActionConfigContent {...defaultProps} error="Error" onRetry={onRetry} />);

      await userEvent.click(screen.getByRole('button', { name: 'Retry' }));

      expect(onRetry).toHaveBeenCalledTimes(1);
    });

    it('does not render schema fields in error state', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          error="Error"
          action={mockAction}
          mainFields={mockMainFields}
        />,
      );

      expect(screen.queryByTestId('schema-field-to')).not.toBeInTheDocument();
    });
  });

  describe('no action state', () => {
    it('renders placeholder message when action is undefined', () => {
      render(<ActionConfigContent {...defaultProps} action={undefined} />);

      expect(screen.getByText('Action configuration not available.')).toBeInTheDocument();
    });

    it('does not render ConnectionSelector when no action', () => {
      render(<ActionConfigContent {...defaultProps} action={undefined} />);

      expect(screen.queryByTestId('connection-selector')).not.toBeInTheDocument();
    });
  });

  describe('empty schema state', () => {
    it('shows no configuration message when mainFields is empty', () => {
      render(<ActionConfigContent {...defaultProps} action={mockAction} mainFields={[]} />);

      expect(
        screen.getByText('No additional configuration required for this action.'),
      ).toBeInTheDocument();
    });

    it('does not render SchemaFieldRenderer when no fields', () => {
      render(<ActionConfigContent {...defaultProps} action={mockAction} mainFields={[]} />);

      expect(screen.queryByTestId(/schema-field-/)).not.toBeInTheDocument();
    });
  });

  describe('connection selector', () => {
    it('renders ConnectionSelector when action requires connection', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockActionWithConnection}
          mainFields={mockMainFields}
        />,
      );

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

    it('passes integration to ConnectionSelector', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockActionWithConnection}
          mainFields={mockMainFields}
        />,
      );

      expect(screen.getByTestId('connection-selector')).toHaveAttribute(
        'data-integration',
        'mailchimp',
      );
    });

    it('passes connection_id from actionConfig', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockActionWithConnection}
          mainFields={mockMainFields}
          actionConfig={{ connection_id: 'conn-456' }}
        />,
      );

      expect(screen.getByTestId('connection-selector')).toHaveAttribute('data-value', 'conn-456');
    });

    it('calls onFieldChange when connection is selected', async () => {
      const onFieldChange = vi.fn();
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockActionWithConnection}
          mainFields={mockMainFields}
          onFieldChange={onFieldChange}
        />,
      );

      await userEvent.click(screen.getByTestId('select-connection'));

      expect(onFieldChange).toHaveBeenCalledWith('connection_id', 'conn-123');
    });

    it('does not render ConnectionSelector when action does not require connection', () => {
      render(
        <ActionConfigContent {...defaultProps} action={mockAction} mainFields={mockMainFields} />,
      );

      expect(screen.queryByTestId('connection-selector')).not.toBeInTheDocument();
    });

    it('does not render ConnectionSelector when action has no integration', () => {
      const actionWithoutIntegration = {
        ...mockActionWithConnection,
        integration: undefined,
      };
      render(
        <ActionConfigContent
          {...defaultProps}
          action={actionWithoutIntegration as unknown as Action}
          mainFields={mockMainFields}
        />,
      );

      expect(screen.queryByTestId('connection-selector')).not.toBeInTheDocument();
    });
  });

  describe('main fields rendering', () => {
    it('renders SchemaFieldRenderer for each main field', () => {
      render(
        <ActionConfigContent {...defaultProps} action={mockAction} mainFields={mockMainFields} />,
      );

      expect(screen.getByTestId('schema-field-to')).toBeInTheDocument();
      expect(screen.getByTestId('schema-field-subject')).toBeInTheDocument();
    });

    it('passes field values from actionConfig', () => {
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockAction}
          mainFields={mockMainFields}
          actionConfig={{ to: 'test@example.com', subject: 'Hello' }}
        />,
      );

      expect(screen.getByTestId('schema-field-to')).toHaveAttribute(
        'data-value',
        'test@example.com',
      );
      expect(screen.getByTestId('schema-field-subject')).toHaveAttribute('data-value', 'Hello');
    });

    it('renders fields in order', () => {
      render(
        <ActionConfigContent {...defaultProps} action={mockAction} mainFields={mockMainFields} />,
      );

      const fields = screen.getAllByTestId(/schema-field-/);
      expect(fields[0]).toHaveAttribute('data-testid', 'schema-field-to');
      expect(fields[1]).toHaveAttribute('data-testid', 'schema-field-subject');
    });

    it('calls onFieldChange when field value changes', async () => {
      const onFieldChange = vi.fn();
      render(
        <ActionConfigContent
          {...defaultProps}
          action={mockAction}
          mainFields={mockMainFields}
          onFieldChange={onFieldChange}
        />,
      );

      await userEvent.type(screen.getByTestId('input-to'), 'a');

      expect(onFieldChange).toHaveBeenCalledWith('to', 'a');
    });
  });
});
