/**
 * SessionCoreModule 单元测试
 *
 * 功能描述：
 * - 测试 SessionCoreModule 的动态模块配置功能
 * - 验证 forFeature 方法的正确行为
 * - 确保依赖注入配置正确
 *
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-14
 * @lastModified 2026-01-14
 */

import { Test, TestingModule } from '@nestjs/testing';
import { SessionCoreModule } from './session_core.module';
import {
  SESSION_QUERY_SERVICE,
  SESSION_MANAGER_SERVICE,
  ISessionQueryService,
  ISessionManagerService,
  IGameSession,
  IContextInfo,
} from './session_core.interfaces';

class MockSessionQueryService implements ISessionQueryService {
  async getSession(): Promise<IGameSession | null> {
    return null;
  }
  async getSocketsInMap(): Promise<string[]> {
    return [];
  }
}

class MockSessionManagerService implements ISessionManagerService {
  async getSession(): Promise<IGameSession | null> {
    return null;
  }
  async getSocketsInMap(): Promise<string[]> {
    return [];
  }
  async createSession(
    socketId: string,
    userId: string,
    zulipQueueId: string,
  ): Promise<IGameSession> {
    return {
      socketId,
      userId,
      username: 'test',
      zulipQueueId,
      currentMap: 'default',
      position: { x: 0, y: 0 },
      lastActivity: new Date(),
      createdAt: new Date(),
    };
  }
  async injectContext(): Promise<IContextInfo> {
    return { stream: 'test' };
  }
  async updatePlayerPosition(): Promise<boolean> {
    return true;
  }
  async destroySession(): Promise<boolean> {
    return true;
  }
  async cleanupExpiredSessions(): Promise<{
    cleanedCount: number;
    zulipQueueIds: string[];
  }> {
    return { cleanedCount: 0, zulipQueueIds: [] };
  }
}

describe('SessionCoreModule', () => {
  describe('forFeature', () => {
    it('should return dynamic module with empty providers when no options', () => {
      const result = SessionCoreModule.forFeature({});
      expect(result.module).toBe(SessionCoreModule);
      expect(result.providers).toEqual([]);
      expect(result.exports).toEqual([]);
    });

    it('should register sessionQueryProvider when provided', () => {
      const result = SessionCoreModule.forFeature({
        sessionQueryProvider: {
          provide: SESSION_QUERY_SERVICE,
          useClass: MockSessionQueryService,
        },
      });
      expect(result.providers).toHaveLength(1);
      expect(result.exports).toContain(SESSION_QUERY_SERVICE);
    });

    it('should register sessionManagerProvider when provided', () => {
      const result = SessionCoreModule.forFeature({
        sessionManagerProvider: {
          provide: SESSION_MANAGER_SERVICE,
          useClass: MockSessionManagerService,
        },
      });
      expect(result.providers).toHaveLength(1);
      expect(result.exports).toContain(SESSION_MANAGER_SERVICE);
    });

    it('should register both providers when both provided', () => {
      const result = SessionCoreModule.forFeature({
        sessionQueryProvider: {
          provide: SESSION_QUERY_SERVICE,
          useClass: MockSessionQueryService,
        },
        sessionManagerProvider: {
          provide: SESSION_MANAGER_SERVICE,
          useClass: MockSessionManagerService,
        },
      });
      expect(result.providers).toHaveLength(2);
      expect(result.exports).toContain(SESSION_QUERY_SERVICE);
      expect(result.exports).toContain(SESSION_MANAGER_SERVICE);
    });
  });

  describe('Module Integration', () => {
    let module: TestingModule;

    afterEach(async () => {
      if (module) {
        await module.close();
      }
    });

    it('should inject sessionQueryService correctly', async () => {
      module = await Test.createTestingModule({
        imports: [
          SessionCoreModule.forFeature({
            sessionQueryProvider: {
              provide: SESSION_QUERY_SERVICE,
              useClass: MockSessionQueryService,
            },
          }),
        ],
      }).compile();

      const service = module.get<ISessionQueryService>(SESSION_QUERY_SERVICE);
      expect(service).toBeInstanceOf(MockSessionQueryService);
    });

    it('should inject sessionManagerService correctly', async () => {
      module = await Test.createTestingModule({
        imports: [
          SessionCoreModule.forFeature({
            sessionManagerProvider: {
              provide: SESSION_MANAGER_SERVICE,
              useClass: MockSessionManagerService,
            },
          }),
        ],
      }).compile();

      const service = module.get<ISessionManagerService>(SESSION_MANAGER_SERVICE);
      expect(service).toBeInstanceOf(MockSessionManagerService);
    });
  });
});
