/**
 * Tests for AI UI Control — Phase 4.12
 *
 * Tests cover:
 * - Command protocol (Task 4.1): UICommand types and validation
 * - useAIUIControl hook (Task 4.3): WebSocket connection and command dispatch
 * - Command execution (Tasks 4.4-4.9): navigate, filter, open_contact, modal, tab, settings
 * - Feedback (Task 4.10): frontend sends confirmation back
 * - Visual indication (Task 4.11): store state for AI active
 */

import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { useAIUIControlStore, type UICommand } from '@/store/aiUIControlStore';

// Mock WebSocket
class MockWebSocket {
  static instances: MockWebSocket[] = [];
  static OPEN = 1;
  static CLOSED = 3;
  readyState = MockWebSocket.OPEN;
  onopen: ((ev: Event) => void) | null = null;
  onmessage: ((ev: MessageEvent) => void) | null = null;
  onclose: ((ev: CloseEvent) => void) | null = null;
  onerror: ((ev: Event) => void) | null = null;
  sentMessages: string[] = [];

  constructor(public url: string) {
    MockWebSocket.instances.push(this);
    setTimeout(() => this.onopen?.(new Event('open')), 0);
  }

  send(data: string) {
    this.sentMessages.push(data);
  }

  close() {
    this.readyState = MockWebSocket.CLOSED;
    this.onclose?.(new CloseEvent('close'));
  }

  // Helper to simulate receiving a message
  receiveMessage(data: unknown) {
    this.onmessage?.({ data: JSON.stringify(data) } as MessageEvent);
  }
}

// Mock react-router-dom
const mockNavigate = vi.fn();
vi.mock('react-router-dom', () => ({
  useNavigate: () => mockNavigate,
  useSearchParams: () => {
    const params = new URLSearchParams();
    return [params, vi.fn()];
  },
  useLocation: () => ({ pathname: '/contacts' }),
}));

// Mock global WebSocket
globalThis.WebSocket = MockWebSocket as unknown as typeof WebSocket;

describe('AI UI Control Store', () => {
  beforeEach(() => {
    useAIUIControlStore.getState().setActiveCommand(null);
    useAIUIControlStore.getState().setActiveModal(null);
    useAIUIControlStore.getState().setActiveTab(null);
    useAIUIControlStore.getState().setPendingFilter(null);
    useAIUIControlStore.getState().setPendingSettings(null);
  });

  it('should initialize with default state', () => {
    const state = useAIUIControlStore.getState();
    expect(state.connected).toBe(false);
    expect(state.activeCommand).toBeNull();
    expect(state.aiActive).toBe(false);
    expect(state.commandHistory).toEqual([]);
  });

  it('should set active command and aiActive flag', () => {
    const cmd: UICommand = {
      command_id: 'test-1',
      action: 'navigate',
      path: '/contacts/123',
    };
    act(() => {
      useAIUIControlStore.getState().setActiveCommand(cmd);
    });
    expect(useAIUIControlStore.getState().activeCommand).toEqual(cmd);
    expect(useAIUIControlStore.getState().aiActive).toBe(true);
  });

  it('should clear pending state', () => {
    const cmd: UICommand = {
      command_id: 'test-2',
      action: 'modal',
      modal: 'edit',
    };
    act(() => {
      useAIUIControlStore.getState().setActiveCommand(cmd);
      useAIUIControlStore.getState().setActiveModal('edit');
      useAIUIControlStore.getState().setPendingFilter({ entity: 'contacts', filter: { type: 'company' } });
    });
    act(() => {
      useAIUIControlStore.getState().clearPending();
    });
    expect(useAIUIControlStore.getState().activeCommand).toBeNull();
    expect(useAIUIControlStore.getState().aiActive).toBe(false);
    expect(useAIUIControlStore.getState().pendingFilter).toBeNull();
  });

  it('should add commands to history (max 50)', () => {
    for (let i = 0; i < 55; i++) {
      act(() => {
        useAIUIControlStore.getState().addCommandToHistory({
          command_id: `cmd-${i}`,
          action: 'navigate',
          path: `/page/${i}`,
        });
      });
    }
    expect(useAIUIControlStore.getState().commandHistory).toHaveLength(50);
    expect(useAIUIControlStore.getState().commandHistory[49].command_id).toBe('cmd-54');
  });
});

describe('AI UI Control — Command Protocol (Task 4.1)', () => {
  it('should define all 6 command types', () => {
    const validActions = ['navigate', 'filter', 'open_contact', 'modal', 'tab', 'settings'];
    expect(validActions).toHaveLength(6);
  });

  it('navigate command should have path field', () => {
    const cmd: UICommand = {
      command_id: 'nav-1',
      action: 'navigate',
      path: '/contacts/123',
    };
    expect(cmd.action).toBe('navigate');
    expect(cmd.path).toBe('/contacts/123');
  });

  it('filter command should have entity and filter fields', () => {
    const cmd: UICommand = {
      command_id: 'filter-1',
      action: 'filter',
      entity: 'contacts',
      filter: { type: 'company', city: 'Berlin' },
    };
    expect(cmd.action).toBe('filter');
    expect(cmd.entity).toBe('contacts');
    expect(cmd.filter).toEqual({ type: 'company', city: 'Berlin' });
  });

  it('open_contact command should have contact_id field', () => {
    const cmd: UICommand = {
      command_id: 'open-1',
      action: 'open_contact',
      contact_id: 'abc-123',
    };
    expect(cmd.action).toBe('open_contact');
    expect(cmd.contact_id).toBe('abc-123');
  });

  it('modal command should have modal field', () => {
    const cmd: UICommand = {
      command_id: 'modal-1',
      action: 'modal',
      modal: 'edit',
    };
    expect(cmd.action).toBe('modal');
    expect(cmd.modal).toBe('edit');
  });

  it('tab command should have tab field', () => {
    const cmd: UICommand = {
      command_id: 'tab-1',
      action: 'tab',
      tab: 'emails',
    };
    expect(cmd.action).toBe('tab');
    expect(cmd.tab).toBe('emails');
  });

  it('settings command should have section, key, value fields', () => {
    const cmd: UICommand = {
      command_id: 'settings-1',
      action: 'settings',
      section: 'ai',
      key: 'model',
      value: 'gpt-4',
    };
    expect(cmd.action).toBe('settings');
    expect(cmd.section).toBe('ai');
    expect(cmd.key).toBe('model');
    expect(cmd.value).toBe('gpt-4');
  });
});

describe('AI UI Control — Store Actions (Tasks 4.4-4.9)', () => {
  beforeEach(() => {
    useAIUIControlStore.getState().setActiveCommand(null);
    useAIUIControlStore.getState().setActiveModal(null);
    useAIUIControlStore.getState().setActiveTab(null);
    useAIUIControlStore.getState().setPendingFilter(null);
    useAIUIControlStore.getState().setPendingSettings(null);
  });

  it('should set active modal (Task 4.7)', () => {
    act(() => {
      useAIUIControlStore.getState().setActiveModal('edit');
    });
    expect(useAIUIControlStore.getState().activeModal).toBe('edit');
  });

  it('should set active tab (Task 4.8)', () => {
    act(() => {
      useAIUIControlStore.getState().setActiveTab('emails');
    });
    expect(useAIUIControlStore.getState().activeTab).toBe('emails');
  });

  it('should set pending filter (Task 4.5)', () => {
    const filter = { entity: 'contacts', filter: { type: 'company' } };
    act(() => {
      useAIUIControlStore.getState().setPendingFilter(filter);
    });
    expect(useAIUIControlStore.getState().pendingFilter).toEqual(filter);
  });

  it('should set pending settings (Task 4.9)', () => {
    const settings = { section: 'ai', key: 'model', value: 'gpt-4' };
    act(() => {
      useAIUIControlStore.getState().setPendingSettings(settings);
    });
    expect(useAIUIControlStore.getState().pendingSettings).toEqual(settings);
  });
});

describe('AI UI Control — Feedback (Task 4.10)', () => {
  it('should store last feedback', () => {
    const feedback = {
      command_id: 'cmd-feedback-1',
      status: 'success' as const,
      action: 'navigate' as const,
      current_path: '/contacts/123',
    };
    act(() => {
      useAIUIControlStore.getState().setLastFeedback(feedback);
    });
    expect(useAIUIControlStore.getState().lastFeedback).toEqual(feedback);
  });
});

describe('AI UI Control — Visual Indication (Task 4.11)', () => {
  it('should set aiActive when command is set', () => {
    act(() => {
      useAIUIControlStore.getState().setActiveCommand({
        command_id: 'vis-1',
        action: 'navigate',
        path: '/dashboard',
      });
    });
    expect(useAIUIControlStore.getState().aiActive).toBe(true);
  });

  it('should clear aiActive when command is cleared', () => {
    act(() => {
      useAIUIControlStore.getState().setActiveCommand({
        command_id: 'vis-2',
        action: 'navigate',
        path: '/dashboard',
      });
      useAIUIControlStore.getState().clearPending();
    });
    expect(useAIUIControlStore.getState().aiActive).toBe(false);
  });
});
