/**
 * Tests for WorkflowEngine
 */

import { WorkflowEngine } from './workflow-engine';
import { Workflow } from '../types/workflow';

describe('WorkflowEngine', () => {
  let engine: WorkflowEngine;

  beforeEach(() => {
    engine = new WorkflowEngine();
  });

  describe('analyze', () => {
    it('should handle empty stack when enhanced features are present', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {},
        migrations: {
          strategy: 'prisma_migrate',
        },
      };

      const result = engine.analyze(workflow);
      expect(result.componentPlans.size).toBe(0);
    });

    it('should handle undefined stack when enhanced features are present', () => {
      const workflow: any = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        // Missing stack property entirely but has enhanced features
        testing: {
          frontend: { framework: 'jest' },
        },
      };

      const result = engine.analyze(workflow);
      expect(result.componentPlans.size).toBe(0);
    });

    it('should analyze a workflow with frontend actions', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [
              {
                id: 'test-component',
                type: 'form-component',
                name: 'TestComponent',
                description: 'Test',
                actions: [
                  {
                    id: 'test-action',
                    trigger: 'click',
                    description: 'Test action',
                    steps: [
                      { id: 'step1', action: 'validate' },
                      { id: 'step2', action: 'submit', depends_on: ['step1'] },
                    ],
                  },
                ],
              },
            ],
          },
        },
      };

      const plan = engine.analyze(workflow);

      expect(plan.componentPlans.size).toBe(1);
      const componentPlan = plan.componentPlans.get('web-app');
      expect(componentPlan).toBeDefined();
      expect(componentPlan?.actionPlans.size).toBe(1);
      const actionPlan = componentPlan?.actionPlans.get('test-action');
      expect(actionPlan?.executionLevels.length).toBe(2);
    });

    it('should analyze a workflow with backend implementations', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
            endpoints: [
              {
                id: 'test-endpoint',
                path: '/test',
                method: 'POST',
                name: 'Test',
                description: 'Test endpoint',
                responses: [{ status: 200, description: 'OK' }],
                implementation: {
                  steps: [
                    { id: 'validate', action: 'validate-schema' },
                    { id: 'process', action: 'process-data', depends_on: ['validate'] },
                    { id: 'respond', action: 'respond', depends_on: ['process'] },
                  ],
                },
              },
            ],
          },
        },
      };

      const plan = engine.analyze(workflow);

      expect(plan.componentPlans.size).toBe(1);
      const componentPlan = plan.componentPlans.get('api');
      expect(componentPlan).toBeDefined();
      expect(componentPlan?.endpointPlans.size).toBe(1);
      const implPlan = componentPlan?.endpointPlans.get('test-endpoint');
      expect(implPlan?.executionLevels.length).toBe(3);
    });

    it('should throw error for circular dependencies in actions', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [
              {
                id: 'test-component',
                type: 'form-component',
                name: 'TestComponent',
                description: 'Test',
                actions: [
                  {
                    id: 'test-action',
                    trigger: 'click',
                    description: 'Test action',
                    steps: [
                      { id: 'step1', action: 'action1', depends_on: ['step2'] },
                      { id: 'step2', action: 'action2', depends_on: ['step1'] },
                    ],
                  },
                ],
              },
            ],
          },
        },
      };

      expect(() => engine.analyze(workflow)).toThrow('Circular dependency');
    });
  });

  describe('validate', () => {
    it('should validate a correct workflow', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
          actors: [{ type: 'customer', role: 'user' }],
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [
              {
                id: 'test-component',
                type: 'form-component',
                name: 'TestComponent',
                description: 'Test',
              },
            ],
          },
        },
      };

      const result = engine.validate(workflow);

      expect(result.valid).toBe(true);
      expect(result.errors.length).toBe(0);
    });

    it('should detect references to non-existent endpoints', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [
              {
                id: 'test-component',
                type: 'form-component',
                name: 'TestComponent',
                description: 'Test',
                actions: [
                  {
                    id: 'test-action',
                    trigger: 'click',
                    description: 'Test action',
                    steps: [
                      {
                        id: 'api-call',
                        action: 'api-call',
                        api_workflow: 'api.nonexistent',
                      },
                    ],
                  },
                ],
              },
            ],
          },
          api: {
            type: 'backend',
            technology: 'typescript/express',
            endpoints: [
              {
                id: 'real-endpoint',
                path: '/test',
                method: 'POST',
                name: 'Test',
                description: 'Test endpoint',
                responses: [{ status: 200, description: 'OK' }],
              },
            ],
          },
        },
      };

      const result = engine.validate(workflow);

      expect(result.valid).toBe(false);
      expect(result.errors.length).toBeGreaterThan(0);
      expect(result.errors[0]).toContain('non-existent endpoint');
    });

    it('should warn about missing actors', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [],
          },
        },
      };

      const result = engine.validate(workflow);

      expect(result.warnings.length).toBeGreaterThan(0);
      expect(result.warnings[0]).toContain('no actors');
    });
  });

  describe('extractTemplateVariables', () => {
    it('should extract template variables from workflow', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
            endpoints: [
              {
                id: 'test-endpoint',
                path: '/test',
                method: 'POST',
                name: 'Test',
                description: 'Test endpoint',
                responses: [{ status: 200, description: 'OK' }],
                implementation: {
                  steps: [
                    {
                      id: 'step1',
                      action: 'query',
                      query: '{{ request.body.id }}',
                    },
                    {
                      id: 'step2',
                      action: 'respond',
                      data: '{{ step1.result }}',
                    },
                  ],
                },
              },
            ],
          },
        },
      };

      const variables = engine.extractTemplateVariables(workflow);

      expect(variables.has('request.body.id')).toBe(true);
      expect(variables.has('step1.result')).toBe(true);
    });
  });

  describe('getDependencies', () => {
    it('should extract workflow dependencies', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          version: '1.0.0',
          name: 'Test',
          description: 'Test workflow',
          relationships: [
            {
              workflow: 'user-registration',
              type: 'prerequisite',
              reason: 'Need users before login',
            },
            {
              workflow: 'session-management',
              type: 'dependent',
              reason: 'Login creates sessions',
            },
          ],
        },
        stack: {
          'web-app': {
            type: 'frontend',
            technology: 'react',
            components: [],
          },
        },
      };

      const dependencies = engine.getDependencies(workflow);

      expect(dependencies).toContain('user-registration');
      expect(dependencies).toContain('session-management');
    });
  });
});
