/**
 * Toolbar Tests
 *
 * Tests the FlowBuilder Toolbar component including:
 * - Basic rendering
 * - Name input behavior
 * - Save status indicators
 * - Undo/redo buttons
 * - Save button states
 * - Active toggle
 * - All callbacks
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { Toolbar, ToolbarProps } from './Toolbar';

describe('Toolbar', () => {
  const defaultProps: ToolbarProps = {
    workflowName: 'My Workflow',
    onNameChange: vi.fn(),
    onNameBlur: vi.fn(),
    nameSaveStatus: 'idle',
    onBack: vi.fn(),
    onSave: vi.fn(),
    canUndo: false,
    canRedo: false,
    onUndo: vi.fn(),
    onRedo: vi.fn(),
    undoCount: 0,
    redoCount: 0,
    isSaving: false,
    hasUnsavedChanges: false,
    isActive: false,
    isActivating: false,
    onToggleActive: vi.fn(),
    canToggleActive: true,
    isPublished: false,
    hasUnpublishedChanges: false,
    isPublishing: false,
    onOpenHistory: vi.fn(),
    onPublish: vi.fn(),
  };

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

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

  describe('basic rendering', () => {
    it('renders workflow name input with current value', () => {
      render(<Toolbar {...defaultProps} />);

      const input = screen.getByDisplayValue('My Workflow');
      expect(input).toBeInTheDocument();
    });

    it('renders back button', () => {
      render(<Toolbar {...defaultProps} />);

      // Back button contains ArrowLeft icon
      const buttons = screen.getAllByRole('button');
      const backButton = buttons.find((btn) => btn.querySelector('svg.lucide-arrow-left'));
      expect(backButton).toBeInTheDocument();
    });

    it('renders undo and redo buttons', () => {
      render(<Toolbar {...defaultProps} />);

      // Undo and Redo buttons are in a history group container
      // There should be 5 buttons total: back, undo, redo, save, (switch is not a button)
      const buttons = screen.getAllByRole('button');
      expect(buttons.length).toBeGreaterThanOrEqual(4);
    });

    it('renders save button', () => {
      render(<Toolbar {...defaultProps} />);

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

    it('renders active toggle', () => {
      render(<Toolbar {...defaultProps} />);

      expect(screen.getByRole('switch')).toBeInTheDocument();
      expect(screen.getByText('Inactive')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Name Input Tests
  // ==========================================================================

  describe('name input', () => {
    it('calls onNameChange when input value changes', () => {
      render(<Toolbar {...defaultProps} />);

      const input = screen.getByDisplayValue('My Workflow');
      fireEvent.change(input, { target: { value: 'New Name' } });

      expect(defaultProps.onNameChange).toHaveBeenCalledWith('New Name');
    });

    it('calls onNameBlur when input loses focus', () => {
      render(<Toolbar {...defaultProps} />);

      const input = screen.getByDisplayValue('My Workflow');
      fireEvent.blur(input);

      expect(defaultProps.onNameBlur).toHaveBeenCalled();
    });
  });

  // ==========================================================================
  // Name Save Status Tests
  // ==========================================================================

  describe('name save status', () => {
    it('shows pencil icon when status is idle', () => {
      render(<Toolbar {...defaultProps} nameSaveStatus="idle" />);

      // Pencil icon should be visible (text-slate-400 class)
      const container = screen.getByDisplayValue('My Workflow').parentElement;
      const svg = container?.querySelector('svg.text-slate-400');
      expect(svg).toBeInTheDocument();
    });

    it('shows spinner when status is saving', () => {
      render(<Toolbar {...defaultProps} nameSaveStatus="saving" />);

      // Loader icon should be visible with animate-spin
      const container = screen.getByDisplayValue('My Workflow').parentElement;
      const svg = container?.querySelector('svg.animate-spin');
      expect(svg).toBeInTheDocument();
    });

    it('shows checkmark when status is saved', () => {
      render(<Toolbar {...defaultProps} nameSaveStatus="saved" />);

      // Check icon should be visible (text-green-500 class)
      const container = screen.getByDisplayValue('My Workflow').parentElement;
      const svg = container?.querySelector('svg.text-green-500');
      expect(svg).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Undo/Redo Button Tests
  // ==========================================================================

  describe('undo/redo buttons', () => {
    // Buttons order: [0] back, [1] undo, [2] redo, [3] save
    const getUndoButton = () => screen.getAllByRole('button')[1];
    const getRedoButton = () => screen.getAllByRole('button')[2];

    it('disables undo button when canUndo is false', () => {
      render(<Toolbar {...defaultProps} canUndo={false} />);

      expect(getUndoButton()).toBeDisabled();
    });

    it('enables undo button when canUndo is true', () => {
      render(<Toolbar {...defaultProps} canUndo={true} undoCount={3} />);

      expect(getUndoButton()).not.toBeDisabled();
    });

    it('disables redo button when canRedo is false', () => {
      render(<Toolbar {...defaultProps} canRedo={false} />);

      expect(getRedoButton()).toBeDisabled();
    });

    it('enables redo button when canRedo is true', () => {
      render(<Toolbar {...defaultProps} canRedo={true} redoCount={2} />);

      expect(getRedoButton()).not.toBeDisabled();
    });

    it('calls onUndo when undo button clicked', () => {
      render(<Toolbar {...defaultProps} canUndo={true} undoCount={1} />);

      fireEvent.click(getUndoButton());

      expect(defaultProps.onUndo).toHaveBeenCalled();
    });

    it('calls onRedo when redo button clicked', () => {
      render(<Toolbar {...defaultProps} canRedo={true} redoCount={1} />);

      fireEvent.click(getRedoButton());

      expect(defaultProps.onRedo).toHaveBeenCalled();
    });

    it('undo and redo buttons are present in the toolbar', async () => {
      render(<Toolbar {...defaultProps} canUndo={true} undoCount={5} />);

      // Verify the buttons are present and functional
      expect(getUndoButton()).toBeInTheDocument();
      expect(getRedoButton()).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Save Button Tests
  // ==========================================================================

  describe('save button', () => {
    it('disables save button when isSaving is true', () => {
      render(<Toolbar {...defaultProps} isSaving={true} hasUnsavedChanges={true} />);

      const saveButton = screen.getByText('Saving').closest('button');
      expect(saveButton).toBeDisabled();
    });

    it('disables save button when hasUnsavedChanges is false', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={false} />);

      const saveButton = screen.getByText('Save').closest('button');
      expect(saveButton).toBeDisabled();
    });

    it('enables save button when hasUnsavedChanges is true and not saving', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={true} isSaving={false} />);

      const saveButton = screen.getByText('Save').closest('button');
      expect(saveButton).not.toBeDisabled();
    });

    it('shows "Saving" text when isSaving', () => {
      render(<Toolbar {...defaultProps} isSaving={true} hasUnsavedChanges={true} />);

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

    it('shows "Save" text when not saving', () => {
      render(<Toolbar {...defaultProps} isSaving={false} />);

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

    it('calls onSave when save button clicked', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={true} />);

      const saveButton = screen.getByText('Save').closest('button');
      fireEvent.click(saveButton!);

      expect(defaultProps.onSave).toHaveBeenCalled();
    });
  });

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

  describe('active toggle', () => {
    it('shows "Active" when isActive is true', () => {
      render(<Toolbar {...defaultProps} isActive={true} />);

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

    it('shows "Inactive" when isActive is false', () => {
      render(<Toolbar {...defaultProps} isActive={false} />);

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

    it('shows "Updating..." when isActivating', () => {
      render(<Toolbar {...defaultProps} isActivating={true} />);

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

    it('disables toggle when canToggleActive is false', () => {
      render(<Toolbar {...defaultProps} canToggleActive={false} />);

      expect(screen.getByRole('switch')).toBeDisabled();
    });

    it('disables toggle when isActivating', () => {
      render(<Toolbar {...defaultProps} isActivating={true} canToggleActive={true} />);

      expect(screen.getByRole('switch')).toBeDisabled();
    });

    it('disables toggle when isSaving', () => {
      render(<Toolbar {...defaultProps} isSaving={true} canToggleActive={true} />);

      expect(screen.getByRole('switch')).toBeDisabled();
    });

    it('calls onToggleActive when toggle clicked', () => {
      render(<Toolbar {...defaultProps} isActive={false} canToggleActive={true} />);

      fireEvent.click(screen.getByRole('switch'));

      expect(defaultProps.onToggleActive).toHaveBeenCalledWith(true);
    });
  });

  // ==========================================================================
  // Back Button Tests
  // ==========================================================================

  describe('back button', () => {
    it('calls onBack when back button clicked', () => {
      render(<Toolbar {...defaultProps} />);

      // Back button contains ArrowLeft icon
      const buttons = screen.getAllByRole('button');
      const backButton = buttons.find((btn) => btn.querySelector('svg.lucide-arrow-left'));
      fireEvent.click(backButton!);

      expect(defaultProps.onBack).toHaveBeenCalled();
    });
  });
});
