import { World, IWorldConfig, IGlobalSystem } from '../../src/ECS/World';
import { Scene } from '../../src/ECS/Scene';
import { EntitySystem } from '../../src/ECS/Systems/EntitySystem';
import { Entity } from '../../src/ECS/Entity';
import { Component } from '../../src/ECS/Component';
import { Matcher } from '../../src/ECS/Utils/Matcher';

// 测试用组件
class TestComponent extends Component {
    public value: number = 0;
    
    constructor(value: number = 0) {
        super();
        this.value = value;
    }
}

class PlayerComponent extends Component {
    public playerId: string;
    
    constructor(playerId: string) {
        super();
        this.playerId = playerId;
    }
}

// 测试用全局系统
class TestGlobalSystem implements IGlobalSystem {
    public readonly name = 'TestGlobalSystem';
    public updateCount: number = 0;
    
    public initialize(): void {
        // 初始化逻辑
    }
    
    public update(): void {
        this.updateCount++;
    }
    
    public reset(): void {
        this.updateCount = 0;
    }
    
    public destroy(): void {
        // 销毁逻辑
    }
}

class TestSceneSystem extends EntitySystem {
    public updateCount = 0;
    
    constructor() {
        super(Matcher.empty().all(PlayerComponent));
    }
    
    protected override process(): void {
        this.updateCount++;
    }
}

// 测试用Scene
class TestScene extends Scene {
    public initializeCalled = false;
    public beginCalled = false;
    public endCalled = false;
    
    public override initialize(): void {
        this.initializeCalled = true;
        super.initialize();
    }
    
    public override begin(): void {
        this.beginCalled = true;
        super.begin();
    }
    
    public override end(): void {
        this.endCalled = true;
        super.end();
    }
}

describe('World', () => {
    let world: World;
    
    beforeEach(() => {
        world = new World({ name: 'TestWorld' });
    });
    
    afterEach(() => {
        if (world) {
            world.destroy();
        }
    });
    
    describe('基础功能', () => {
        test('创建World时应该设置正确的配置', () => {
            const config: IWorldConfig = {
                name: 'GameWorld',
                debug: true,
                maxScenes: 5,
                autoCleanup: false
            };
            
            const testWorld = new World(config);
            
            expect(testWorld.name).toBe('GameWorld');
            expect(testWorld.sceneCount).toBe(0);
            expect(testWorld.isActive).toBe(false);
            expect(testWorld.createdAt).toBeGreaterThan(0);
            
            testWorld.destroy();
        });
        
        test('默认配置应该正确', () => {
            const defaultWorld = new World();
            
            expect(defaultWorld.name).toBe('World');
            expect(defaultWorld.sceneCount).toBe(0);
            expect(defaultWorld.isActive).toBe(false);
            
            defaultWorld.destroy();
        });
    });
    
    describe('Scene管理', () => {
        test('创建Scene应该成功', () => {
            const scene = world.createScene('test-scene');
            
            expect(scene).toBeDefined();
            expect(world.sceneCount).toBe(1);
            expect(world.getSceneIds()).toContain('test-scene');
        });
        
        test('创建Scene时传入自定义Scene实例', () => {
            const customScene = new TestScene();
            const scene = world.createScene('custom-scene', customScene);
            
            expect(scene).toBe(customScene);
            expect(scene.initializeCalled).toBe(true);
            expect(world.sceneCount).toBe(1);
        });
        
        test('重复的Scene ID应该抛出错误', () => {
            world.createScene('duplicate');
            
            expect(() => {
                world.createScene('duplicate');
            }).toThrow("Scene ID 'duplicate' 已存在于World 'TestWorld' 中");
        });
        
        test('超出最大Scene数量限制应该抛出错误', () => {
            const limitedWorld = new World({ maxScenes: 2 });
            
            limitedWorld.createScene('scene1');
            limitedWorld.createScene('scene2');
            
            expect(() => {
                limitedWorld.createScene('scene3');
            }).toThrow("World 'World' 已达到最大Scene数量限制: 2");
            
            limitedWorld.destroy();
        });
        
        test('获取Scene应该正确', () => {
            const scene = world.createScene('get-test');
            const retrievedScene = world.getScene('get-test');
            
            expect(retrievedScene).toBe(scene);
        });
        
        test('获取不存在的Scene应该返回null', () => {
            const scene = world.getScene('non-existent');
            expect(scene).toBeNull();
        });
        
        test('移除Scene应该正确清理', () => {
            const testScene = new TestScene();
            world.createScene('remove-test', testScene);
            world.setSceneActive('remove-test', true);
            
            const removed = world.removeScene('remove-test');
            
            expect(removed).toBe(true);
            expect(world.sceneCount).toBe(0);
            expect(world.getScene('remove-test')).toBeNull();
            expect(testScene.endCalled).toBe(true);
        });
        
        test('移除不存在的Scene应该返回false', () => {
            const removed = world.removeScene('non-existent');
            expect(removed).toBe(false);
        });
        
        test('获取所有Scene应该正确', () => {
            const scene1 = world.createScene('scene1');
            const scene2 = world.createScene('scene2');
            
            const allScenes = world.getAllScenes();
            
            expect(allScenes).toHaveLength(2);
            expect(allScenes).toContain(scene1);
            expect(allScenes).toContain(scene2);
        });
    });
    
    describe('Scene激活管理', () => {
        test('激活Scene应该正确', () => {
            const testScene = new TestScene();
            world.createScene('active-test', testScene);
            
            world.setSceneActive('active-test', true);
            
            expect(world.isSceneActive('active-test')).toBe(true);
            expect(world.getActiveSceneCount()).toBe(1);
            expect(testScene.beginCalled).toBe(true);
        });
        
        test('停用Scene应该正确', () => {
            world.createScene('deactive-test');
            world.setSceneActive('deactive-test', true);
            
            world.setSceneActive('deactive-test', false);
            
            expect(world.isSceneActive('deactive-test')).toBe(false);
            expect(world.getActiveSceneCount()).toBe(0);
        });
        
        test('激活不存在的Scene应该记录警告', () => {
            const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
            
            world.setSceneActive('non-existent', true);
            
            // 注意：这里需要检查具体的日志实现，可能需要调整
            consoleSpy.mockRestore();
        });
    });
    
    describe('全局System管理', () => {
        test('添加全局System应该成功', () => {
            const globalSystem = new TestGlobalSystem();
            
            const addedSystem = world.addGlobalSystem(globalSystem);
            
            expect(addedSystem).toBe(globalSystem);
            expect(world.getGlobalSystem(TestGlobalSystem)).toBe(globalSystem);
        });
        
        test('重复添加相同System应该返回原System', () => {
            const globalSystem = new TestGlobalSystem();
            
            const firstAdd = world.addGlobalSystem(globalSystem);
            const secondAdd = world.addGlobalSystem(globalSystem);
            
            expect(firstAdd).toBe(secondAdd);
            expect(firstAdd).toBe(globalSystem);
        });
        
        test('移除全局System应该成功', () => {
            const globalSystem = new TestGlobalSystem();
            world.addGlobalSystem(globalSystem);
            
            const removed = world.removeGlobalSystem(globalSystem);
            
            expect(removed).toBe(true);
            expect(world.getGlobalSystem(TestGlobalSystem)).toBeNull();
        });
        
        test('移除不存在的System应该返回false', () => {
            const globalSystem = new TestGlobalSystem();
            
            const removed = world.removeGlobalSystem(globalSystem);
            
            expect(removed).toBe(false);
        });
        
        test('获取不存在的System类型应该返回null', () => {
            const system = world.getGlobalSystem(TestGlobalSystem);
            expect(system).toBeNull();
        });
    });
    
    describe('World生命周期', () => {
        test('启动World应该正确', () => {
            const globalSystem = new TestGlobalSystem();
            world.addGlobalSystem(globalSystem);
            
            world.start();
            
            expect(world.isActive).toBe(true);
        });
        
        test('重复启动World应该无效果', () => {
            world.start();
            const firstActive = world.isActive;
            
            world.start();
            
            expect(world.isActive).toBe(firstActive);
        });
        
        test('停止World应该停用所有Scene', () => {
            const testScene = new TestScene();
            world.createScene('stop-test', testScene);
            world.setSceneActive('stop-test', true);
            world.start();
            
            world.stop();
            
            expect(world.isActive).toBe(false);
            expect(world.isSceneActive('stop-test')).toBe(false);
        });
        
        test('销毁World应该清理所有资源', () => {
            const testScene = new TestScene();
            const globalSystem = new TestGlobalSystem();
            
            world.createScene('destroy-test', testScene);
            world.addGlobalSystem(globalSystem);
            world.start();
            
            world.destroy();
            
            expect(world.sceneCount).toBe(0);
            expect(world.isActive).toBe(false);
            expect(testScene.endCalled).toBe(true);
        });
    });
    
    describe('更新逻辑', () => {
        test('updateGlobalSystems应该更新全局系统', () => {
            const globalSystem = new TestGlobalSystem();
            world.addGlobalSystem(globalSystem);
            world.start();
            
            // 创建测试Scene
            const scene = world.createScene('update-test');
            world.setSceneActive('update-test', true);
            
            // 直接测试全局系统更新
            world.updateGlobalSystems();
            
            // 验证全局System被正确调用
            expect(globalSystem.updateCount).toBeGreaterThan(0);
        });
        
        test('未激活的World不应该更新', () => {
            const globalSystem = new TestGlobalSystem();
            world.addGlobalSystem(globalSystem);
            // 不启动World
            
            world.updateGlobalSystems();
            
            expect(globalSystem.updateCount).toBe(0);
        });
        
        test('updateScenes应该更新激活的Scene', () => {
            const scene1 = world.createScene('scene1');
            const scene2 = world.createScene('scene2');
            
            scene1.addEntityProcessor(new TestSceneSystem());
            scene2.addEntityProcessor(new TestSceneSystem());
            
            world.start();
            world.setSceneActive('scene1', true);
            // scene2保持未激活
            
            world.updateScenes();
            
            // 这里需要根据具体的Scene更新实现来验证
            // 由于Scene.update()的具体实现可能不同，这里主要测试调用不出错
            expect(() => world.updateScenes()).not.toThrow();
        });
    });
    
    describe('状态和统计', () => {
        test('获取World状态应该正确', () => {
            world.createScene('status-scene1');
            world.createScene('status-scene2');
            world.setSceneActive('status-scene1', true);
            world.addGlobalSystem(new TestGlobalSystem());
            world.start();
            
            const status = world.getStatus();
            
            expect(status.name).toBe('TestWorld');
            expect(status.isActive).toBe(true);
            expect(status.sceneCount).toBe(2);
            expect(status.activeSceneCount).toBe(1);
            expect(status.globalSystemCount).toBe(1);
            expect(status.createdAt).toBeGreaterThan(0);
            expect(status.scenes).toHaveLength(2);
            
            const activeScene = status.scenes.find(s => s.id === 'status-scene1');
            expect(activeScene?.isActive).toBe(true);
            
            const inactiveScene = status.scenes.find(s => s.id === 'status-scene2');
            expect(inactiveScene?.isActive).toBe(false);
        });
        
        test('获取World统计应该包含基本信息', () => {
            world.addGlobalSystem(new TestGlobalSystem());
            
            const scene = world.createScene('stats-scene');
            const entity = scene.createEntity('stats-entity');
            entity.addComponent(new TestComponent());
            
            const stats = world.getStats();
            
            expect(stats).toHaveProperty('totalEntities');
            expect(stats).toHaveProperty('totalSystems');
            expect(stats).toHaveProperty('memoryUsage');
            expect(stats).toHaveProperty('performance');
            expect(stats.totalSystems).toBeGreaterThanOrEqual(1);
        });
    });
    
    describe('自动清理功能', () => {
        test('自动清理应该移除空闲Scene', async () => {
            // 创建一个启用自动清理的World
            const autoCleanWorld = new World({
                name: 'AutoCleanWorld',
                autoCleanup: true,
                maxScenes: 10
            });
            
            // 创建一个空Scene
            autoCleanWorld.createScene('empty-scene');
            autoCleanWorld.start();
            
            // 手动触发清理检查
            autoCleanWorld.updateScenes();
            
            // 由于清理策略基于时间，这里主要测试不会出错
            expect(() => autoCleanWorld.updateScenes()).not.toThrow();
            
            autoCleanWorld.destroy();
        });
    });
    
    describe('错误处理', () => {
        test('Scene ID为空时应该创建默认ID', () => {
            expect(() => {
                world.createScene('');
            }).not.toThrow();
        });
        
        test('极限情况下的资源管理', () => {
            // 创建大量Scene
            for (let i = 0; i < 5; i++) {
                world.createScene(`scene_${i}`);
                world.setSceneActive(`scene_${i}`, true);
            }
            
            // 添加多个全局System
            for (let i = 0; i < 3; i++) {
                world.addGlobalSystem(new TestGlobalSystem());
            }
            
            world.start();
            
            // 测试批量清理
            expect(() => world.destroy()).not.toThrow();
        });
    });
});