import { UXDesignerAgent, UserResearch, Wireframe } from '../agents/ux-designer';
import { KnowledgeGraph } from '../knowledge-graph';
import { AgentWorkflowSystem } from '../agent-workflow';

jest.mock('../knowledge-graph');
jest.mock('../agent-workflow');

describe('UXDesignerAgent', () => {
  let uxDesigner: UXDesignerAgent;
  let mockKnowledgeGraph: jest.Mocked<KnowledgeGraph>;
  let mockWorkflow: jest.Mocked<AgentWorkflowSystem>;

  beforeEach(() => {
    mockKnowledgeGraph = new KnowledgeGraph() as jest.Mocked<KnowledgeGraph>;
    mockWorkflow = new AgentWorkflowSystem(mockKnowledgeGraph) as jest.Mocked<AgentWorkflowSystem>;
    uxDesigner = new UXDesignerAgent(mockKnowledgeGraph, mockWorkflow);
  });

  describe('conductUserResearch', () => {
    it('creates research and adds to knowledge graph', async () => {
      const research = await uxDesigner.conductUserResearch('persona', { userType: 'developer' });

      expect(research).toMatchObject({
        type: 'persona',
        data: { userType: 'developer' },
        insights: [],
        recommendations: []
      });

      expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({
        id: expect.stringContaining('research:'),
        type: 'user_research',
        data: research
      });
    });
  });

  describe('createWireframe', () => {
    it('creates wireframe and adds to knowledge graph', async () => {
      const wireframe = await uxDesigner.createWireframe('Login Page', 'User login interface');

      expect(wireframe).toMatchObject({
        name: 'Login Page',
        description: 'User login interface',
        components: [],
        interactions: []
      });

      expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({
        id: expect.stringContaining('wireframe:'),
        type: 'wireframe',
        data: wireframe
      });
    });
  });

  describe('addComponentToWireframe', () => {
    it('adds component to existing wireframe', async () => {
      const mockWireframe = {
        id: 'wireframe:123',
        type: 'wireframe',
        data: {
          components: []
        }
      };

      mockKnowledgeGraph.findNodes.mockResolvedValueOnce([mockWireframe]);

      const component = {
        id: 'btn1',
        type: 'button',
        position: { x: 10, y: 20 },
        size: { width: 100, height: 40 },
        props: { label: 'Submit' }
      };

      await uxDesigner.addComponentToWireframe('123', component);

      expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({
        id: 'wireframe:123',
        data: expect.objectContaining({
          components: [component]
        })
      });
    });

    it('throws error if wireframe not found', async () => {
      mockKnowledgeGraph.findNodes.mockResolvedValueOnce([]);

      await expect(
        uxDesigner.addComponentToWireframe('invalid', {
          id: 'btn1',
          type: 'button',
          position: { x: 0, y: 0 },
          size: { width: 0, height: 0 },
          props: {}
        })
      ).rejects.toThrow('Wireframe invalid not found');
    });
  });

  describe('validateWireframe', () => {
    it('validates wireframe with valid components and interactions', async () => {
      const mockWireframe = {
        id: 'wireframe:123',
        type: 'wireframe',
        data: {
          components: [
            {
              id: 'btn1',
              type: 'button',
              position: { x: 10, y: 20 },
              size: { width: 100, height: 40 }
            }
          ],
          interactions: [
            {
              sourceId: 'btn1',
              targetId: 'btn1',
              type: 'click',
              description: 'Submit form'
            }
          ]
        }
      };

      mockKnowledgeGraph.findNodes.mockResolvedValueOnce([mockWireframe]);

      const result = await uxDesigner.validateWireframe('123');
      expect(result.valid).toBe(true);
      expect(result.errors).toHaveLength(0);
    });

    it('returns errors for invalid wireframe', async () => {
      const mockWireframe = {
        id: 'wireframe:123',
        type: 'wireframe',
        data: {
          components: [],
          interactions: [
            {
              sourceId: 'invalid',
              targetId: 'alsoinvalid',
              type: 'click',
              description: 'Invalid interaction'
            }
          ]
        }
      };

      mockKnowledgeGraph.findNodes.mockResolvedValueOnce([mockWireframe]);

      const result = await uxDesigner.validateWireframe('123');
      expect(result.valid).toBe(false);
      expect(result.errors).toContain('Wireframe must have at least one component');
      expect(result.errors).toContain(
        'Interaction references non-existent component: invalid -> alsoinvalid'
      );
    });
  });
}); 