/**
 * VariableInput Tests
 *
 * Tests the rich text variable input component including:
 * - Basic rendering
 * - Variable button state
 * - Disabled state
 * - Multiline mode
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import { VariableInput } from './VariableInput';
import { AvailableContext } from '../types/workflow-context';

// Mock TipTap modules
vi.mock('@tiptap/react', () => ({
  useEditor: () => ({
    chain: () => ({ focus: () => ({ run: vi.fn() }) }),
    commands: { setContent: vi.fn() },
    getJSON: () => ({ type: 'doc', content: [] }),
    state: { selection: { from: 0 } },
    view: {
      dom: document.createElement('div'),
      coordsAtPos: () => ({ top: 0, left: 0, bottom: 0 }),
    },
    on: vi.fn(),
    off: vi.fn(),
    setEditable: vi.fn(),
  }),
  EditorContent: ({ editor: _editor }: { editor: unknown }) => (
    <div data-testid="editor-content">Editor Content</div>
  ),
}));

vi.mock('@tiptap/extension-document', () => ({ default: {} }));
vi.mock('@tiptap/extension-paragraph', () => ({ default: {} }));
vi.mock('@tiptap/extension-text', () => ({ default: {} }));
vi.mock('@tiptap/extension-placeholder', () => ({
  default: { configure: () => ({}) },
}));
vi.mock('./tiptap/VariableNode', () => ({ VariableNode: {} }));
vi.mock('./tiptap/SuggestionDropdown', () => ({
  SuggestionDropdown: () => null,
}));
vi.mock('./tiptap/variableUtils', () => ({
  deserializeToTipTap: () => ({ type: 'doc', content: [] }),
  deserializeMultilineToTipTap: () => ({ type: 'doc', content: [] }),
  serializeFromTipTap: () => '',
}));

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

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

  const contextWithVariables: AvailableContext = {
    groups: [
      {
        namespace: 'Trigger',
        sourceName: 'User Registration',
        sourceType: 'trigger',
        variables: [
          {
            path: 'Trigger.user_email',
            label: 'User Email',
            source: 'User Registration',
            namespace: 'Trigger',
            type: 'string',
            description: 'The email address of the registered user',
            example: 'user@example.com',
          },
        ],
      },
    ],
  };

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

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

  describe('basic rendering', () => {
    it('renders the editor content', () => {
      render(
        <VariableInput value="" onChange={mockOnChange} availableContext={contextWithVariables} />,
      );

      expect(screen.getByTestId('editor-content')).toBeInTheDocument();
    });

    it('renders variable button', () => {
      render(
        <VariableInput value="" onChange={mockOnChange} availableContext={contextWithVariables} />,
      );

      const variableButton = screen.getByRole('button');
      expect(variableButton).toBeInTheDocument();
    });

    it('applies custom className', () => {
      const { container } = render(
        <VariableInput
          value=""
          onChange={mockOnChange}
          availableContext={contextWithVariables}
          className="custom-class"
        />,
      );

      expect(container.querySelector('.custom-class')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Variable Button State Tests
  // ==========================================================================

  describe('variable button state', () => {
    it('enables variable button when context has variables', () => {
      render(
        <VariableInput value="" onChange={mockOnChange} availableContext={contextWithVariables} />,
      );

      const variableButton = screen.getByRole('button');
      expect(variableButton).not.toBeDisabled();
    });

    it('disables variable button when context has no variables', () => {
      render(<VariableInput value="" onChange={mockOnChange} availableContext={emptyContext} />);

      const variableButton = screen.getByRole('button');
      expect(variableButton).toBeDisabled();
    });

    it('disables variable button when input is disabled', () => {
      render(
        <VariableInput
          value=""
          onChange={mockOnChange}
          availableContext={contextWithVariables}
          disabled
        />,
      );

      const variableButton = screen.getByRole('button');
      expect(variableButton).toBeDisabled();
    });
  });

  // ==========================================================================
  // Disabled State Tests
  // ==========================================================================

  describe('disabled state', () => {
    it('applies disabled styles when disabled', () => {
      const { container } = render(
        <VariableInput
          value=""
          onChange={mockOnChange}
          availableContext={contextWithVariables}
          disabled
        />,
      );

      expect(container.querySelector('.cursor-not-allowed')).toBeInTheDocument();
      expect(container.querySelector('.opacity-60')).toBeInTheDocument();
    });
  });

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

  describe('multiline mode', () => {
    it('applies min-height for multiline mode', () => {
      const { container } = render(
        <VariableInput
          value=""
          onChange={mockOnChange}
          availableContext={contextWithVariables}
          multiline
        />,
      );

      expect(container.querySelector('.min-h-\\[100px\\]')).toBeInTheDocument();
    });

    it('applies smaller min-height for single-line mode', () => {
      const { container } = render(
        <VariableInput
          value=""
          onChange={mockOnChange}
          availableContext={contextWithVariables}
          multiline={false}
        />,
      );

      expect(container.querySelector('.min-h-\\[38px\\]')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Tooltip Tests
  // ==========================================================================

  describe('tooltip', () => {
    it('renders tooltip provider', () => {
      render(
        <VariableInput value="" onChange={mockOnChange} availableContext={contextWithVariables} />,
      );

      // The variable icon button should be in a tooltip trigger
      const button = screen.getByRole('button');
      expect(button).toBeInTheDocument();
    });
  });
});
