import { describe, it, expect, beforeEach, vi } from '@jest/globals';
import { CoreEngineService } from '../../core/engine/CoreEngineService';
import { RuleEngineService } from '../../core/engine/RuleEngineService';
import { WorkflowEngineService } from '../../core/engine/WorkflowEngineService';
import { RedisService } from '../../core/cache/RedisService';

describe('CoreEngineService', () => {
  let coreEngineService: CoreEngineService;
  let mockRuleEngineService: jest.Mocked<RuleEngineService>;
  let mockWorkflowEngineService: jest.Mocked<WorkflowEngineService>;
  let mockRedisService: jest.Mocked<RedisService>;

  beforeEach(() => {
    // 创建模拟对象
    mockRuleEngineService = {
      executeRules: vi.fn(),
      registerRule: vi.fn(),
      getStatus: vi.fn()
    } as any;

    mockWorkflowEngineService = {
      executeWorkflow: vi.fn(),
      registerWorkflow: vi.fn(),
      getStatus: vi.fn()
    } as any;

    mockRedisService = {
      get: vi.fn(),
      set: vi.fn(),
      getStatus: vi.fn()
    } as any;

    // 初始化CoreEngineService
    coreEngineService = new CoreEngineService(
      mockRuleEngineService,
      mockWorkflowEngineService,
      mockRedisService
    );
  });

  describe('processBusinessRequest', () => {
    it('should return cached result when cache exists', async () => {
      const request = { id: '1', type: 'test' };
      const context = { tenantId: 'test-tenant' };
      const cachedResult = { success: true, data: 'cached data' };

      // 模拟缓存命中
      mockRedisService.get.mockResolvedValue(cachedResult);

      const result = await coreEngineService.processBusinessRequest(request, context);

      expect(result).toEqual(cachedResult);
      expect(mockRedisService.get).toHaveBeenCalledWith('core-engine:{"id":"1","type":"test"}');
      expect(mockRuleEngineService.executeRules).not.toHaveBeenCalled();
      expect(mockWorkflowEngineService.executeWorkflow).not.toHaveBeenCalled();
    });

    it('should process request when cache does not exist', async () => {
      const request = { id: '1', type: 'test' };
      const context = { tenantId: 'test-tenant' };
      const ruleResult = { workflowId: 'workflow-1', data: { processed: true } };
      const workflowResult = { success: true, data: 'processed data' };

      // 模拟缓存未命中
      mockRedisService.get.mockResolvedValue(null);
      // 模拟规则引擎执行结果
      mockRuleEngineService.executeRules.mockResolvedValue(ruleResult);
      // 模拟工作流执行结果
      mockWorkflowEngineService.executeWorkflow.mockResolvedValue(workflowResult);
      // 模拟缓存设置
      mockRedisService.set.mockResolvedValue(true);

      const result = await coreEngineService.processBusinessRequest(request, context);

      expect(result).toEqual(workflowResult);
      expect(mockRedisService.get).toHaveBeenCalledWith('core-engine:{"id":"1","type":"test"}');
      expect(mockRuleEngineService.executeRules).toHaveBeenCalledWith(request, context);
      expect(mockWorkflowEngineService.executeWorkflow).toHaveBeenCalledWith(ruleResult.workflowId, ruleResult.data);
      expect(mockRedisService.set).toHaveBeenCalledWith('core-engine:{"id":"1","type":"test"}', workflowResult, 3600);
    });

    it('should throw error when processing fails', async () => {
      const request = { id: '1', type: 'test' };
      const context = { tenantId: 'test-tenant' };
      const error = new Error('Processing error');

      // 模拟缓存未命中
      mockRedisService.get.mockResolvedValue(null);
      // 模拟规则引擎执行失败
      mockRuleEngineService.executeRules.mockRejectedValue(error);

      await expect(coreEngineService.processBusinessRequest(request, context)).rejects.toThrow('Processing error');
    });
  });

  describe('registerBusinessRule', () => {
    it('should register business rule', async () => {
      const rule = { id: 'rule-1', condition: 'test condition' };
      const expectedRuleId = 'rule-1';

      mockRuleEngineService.registerRule.mockResolvedValue(expectedRuleId);

      const result = await coreEngineService.registerBusinessRule(rule);

      expect(result).toBe(expectedRuleId);
      expect(mockRuleEngineService.registerRule).toHaveBeenCalledWith(rule);
    });
  });

  describe('registerWorkflow', () => {
    it('should register workflow', async () => {
      const workflow = { id: 'workflow-1', steps: [] };
      const expectedWorkflowId = 'workflow-1';

      mockWorkflowEngineService.registerWorkflow.mockResolvedValue(expectedWorkflowId);

      const result = await coreEngineService.registerWorkflow(workflow);

      expect(result).toBe(expectedWorkflowId);
      expect(mockWorkflowEngineService.registerWorkflow).toHaveBeenCalledWith(workflow);
    });
  });

  describe('getSystemStatus', () => {
    it('should return system status', async () => {
      const ruleEngineStatus = { status: 'healthy' };
      const workflowEngineStatus = { status: 'healthy' };
      const redisStatus = { status: 'healthy' };

      mockRuleEngineService.getStatus.mockResolvedValue(ruleEngineStatus);
      mockWorkflowEngineService.getStatus.mockResolvedValue(workflowEngineStatus);
      mockRedisService.getStatus.mockResolvedValue(redisStatus);

      const result = await coreEngineService.getSystemStatus();

      expect(result.status).toBe('healthy');
      expect(result.services.ruleEngine).toEqual(ruleEngineStatus);
      expect(result.services.workflowEngine).toEqual(workflowEngineStatus);
      expect(result.services.redis).toEqual(redisStatus);
    });
  });
});
