/**
 * 管理员核心服务集成测试
 * 
 * 功能描述：
 * - 测试AdminCoreService与真实依赖的集成
 * - 验证完整的管理员认证流程
 * - 测试配置服务和用户服务的真实交互
 * - 验证引导创建功能的端到端流程
 * 
 * 职责分离：
 * - 集成测试验证模块间协作
 * - 使用真实的服务依赖
 * - 测试完整的业务流程
 * 
 * 最近修改：
 * - 2026-01-07: 功能新增 - 创建管理员核心服务集成测试
 * 
 * @author jianuo
 * @version 1.0.0
 * @since 2026-01-07
 * @lastModified 2026-01-07
 */

import { Test, TestingModule } from '@nestjs/testing';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AdminCoreService } from './admin_core.service';
import { UsersMemoryService } from '../db/users/users_memory.service';
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
import * as bcrypt from 'bcrypt';

describe('AdminCoreService Integration', () => {
  let service: AdminCoreService;
  let configService: ConfigService;
  let usersService: UsersMemoryService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath: [],
          load: [
            () => ({
              ADMIN_TOKEN_SECRET: 'test-secret-for-integration-0123456789',
              ADMIN_TOKEN_TTL_SECONDS: '3600',
              ADMIN_BOOTSTRAP_ENABLED: 'false',
            }),
          ],
        }),
      ],
      providers: [
        AdminCoreService,
        UsersMemoryService,
        {
          provide: 'UsersService',
          useExisting: UsersMemoryService,
        },
      ],
    }).compile();

    service = module.get<AdminCoreService>(AdminCoreService);
    configService = module.get<ConfigService>(ConfigService);
    usersService = module.get<UsersMemoryService>(UsersMemoryService);
  });

  afterEach(async () => {
    // 清理测试数据
    const allUsers = await usersService.findAll(1000, 0, true);
    for (const user of allUsers) {
      await usersService.remove(user.id).catch(() => {});
    }
  });

  describe('Complete Admin Authentication Flow', () => {
    it('should create admin user and perform full login flow', async () => {
      // 1. 生成真实的密码哈希
      const password = 'TestAdmin123';
      const passwordHash = await bcrypt.hash(password, 12);

      // 2. 创建管理员用户
      const adminUser = await usersService.create({
        username: 'testadmin',
        password_hash: passwordHash,
        nickname: '测试管理员',
        role: 9,
        email: 'admin@test.com',
        email_verified: true,
      });

      expect(adminUser.role).toBe(9);

      // 3. 执行登录
      const loginResult = await service.login({
        identifier: 'testadmin',
        password: password,
      });

      expect(loginResult.admin.username).toBe('testadmin');
      expect(loginResult.admin.role).toBe(9);
      expect(loginResult.access_token).toBeDefined();
      expect(loginResult.expires_at).toBeGreaterThan(Date.now());

      // 4. 验证生成的Token
      const payload = service.verifyToken(loginResult.access_token);
      expect(payload.adminId).toBe(adminUser.id.toString());
      expect(payload.username).toBe('testadmin');
      expect(payload.role).toBe(9);
    });

    it('should reject non-admin user login', async () => {
      const password = 'TestUser123';
      const passwordHash = await bcrypt.hash(password, 12);

      await usersService.create({
        username: 'regularuser',
        password_hash: passwordHash,
        nickname: '普通用户',
        role: 1,
        email: 'user@test.com',
        email_verified: true,
      });

      await expect(
        service.login({
          identifier: 'regularuser',
          password: password,
        })
      ).rejects.toThrow(UnauthorizedException);
    });
  });

  describe('Password Reset Integration', () => {
    it('should reset user password successfully', async () => {
      const user = await usersService.create({
        username: 'testuser',
        password_hash: 'old-hash',
        nickname: '测试用户',
        role: 1,
        email: 'testuser@test.com',
        email_verified: true,
      });

      await service.resetUserPassword(user.id, 'NewPassword123');

      const updatedUser = await usersService.findOne(user.id);
      expect(updatedUser?.password_hash).not.toBe('old-hash');
      expect(updatedUser?.password_hash).toBeDefined();
    });

    it('should reject weak password in reset', async () => {
      const user = await usersService.create({
        username: 'testuser2',
        password_hash: 'old-hash',
        nickname: '测试用户2',
        role: 1,
        email: 'testuser2@test.com',
        email_verified: true,
      });

      await expect(
        service.resetUserPassword(user.id, 'weak')
      ).rejects.toThrow(BadRequestException);
    });
  });

  describe('Bootstrap Integration', () => {
    it('should create admin when bootstrap enabled', async () => {
      // 重新创建模块，启用引导功能
      const bootstrapModule: TestingModule = await Test.createTestingModule({
        imports: [
          ConfigModule.forRoot({
            isGlobal: true,
            envFilePath: [],
            load: [
              () => ({
                ADMIN_TOKEN_SECRET: 'test-secret-for-integration-0123456789',
                ADMIN_TOKEN_TTL_SECONDS: '3600',
                ADMIN_BOOTSTRAP_ENABLED: 'true',
                ADMIN_USERNAME: 'bootstrapadmin',
                ADMIN_PASSWORD: 'BootstrapAdmin123',
                ADMIN_NICKNAME: '引导管理员',
              }),
            ],
          }),
        ],
        providers: [
          AdminCoreService,
          UsersMemoryService,
          {
            provide: 'UsersService',
            useExisting: UsersMemoryService,
          },
        ],
      }).compile();

      const bootstrapService = bootstrapModule.get<AdminCoreService>(AdminCoreService);
      const bootstrapUsersService = bootstrapModule.get<UsersMemoryService>(UsersMemoryService);

      // 触发模块初始化
      await bootstrapService.onModuleInit();

      // 验证管理员已创建
      const createdAdmin = await bootstrapUsersService.findByUsername('bootstrapadmin');
      expect(createdAdmin).toBeDefined();
      expect(createdAdmin?.role).toBe(9);
      expect(createdAdmin?.nickname).toBe('引导管理员');
      expect(createdAdmin?.email_verified).toBe(true);

      // 验证可以登录
      const loginResult = await bootstrapService.login({
        identifier: 'bootstrapadmin',
        password: 'BootstrapAdmin123',
      });

      expect(loginResult.admin.username).toBe('bootstrapadmin');
      expect(loginResult.admin.role).toBe(9);
    });
  });

  describe('Configuration Integration', () => {
    it('should use configured token TTL', async () => {
      const password = 'TestAdmin123';
      const passwordHash = await bcrypt.hash(password, 12);

      const adminUser = await usersService.create({
        username: 'ttladmin',
        password_hash: passwordHash,
        nickname: 'TTL管理员',
        role: 9,
        email: 'ttladmin@test.com',
        email_verified: true,
      });

      const now = Date.now();
      const loginResult = await service.login({
        identifier: 'ttladmin',
        password: password,
      });

      // 验证TTL设置（3600秒 = 1小时）
      const expectedExpiry = now + 3600 * 1000;
      expect(loginResult.expires_at).toBeGreaterThan(now);
      expect(loginResult.expires_at).toBeLessThanOrEqual(expectedExpiry + 1000); // 允许1秒误差
    });

    it('should throw error when token secret is too short', async () => {
      // 创建配置错误的模块
      const badConfigModule: TestingModule = await Test.createTestingModule({
        imports: [
          ConfigModule.forRoot({
            isGlobal: true,
            envFilePath: [],
            load: [
              () => ({
                ADMIN_TOKEN_SECRET: 'short', // 太短的密钥
                ADMIN_TOKEN_TTL_SECONDS: '3600',
                ADMIN_BOOTSTRAP_ENABLED: 'false',
              }),
            ],
          }),
        ],
        providers: [
          AdminCoreService,
          UsersMemoryService,
          {
            provide: 'UsersService',
            useExisting: UsersMemoryService,
          },
        ],
      }).compile();

      const badConfigService = badConfigModule.get<AdminCoreService>(AdminCoreService);

      // 验证在获取Token密钥时抛出异常
      expect(() => {
        (badConfigService as any).getAdminTokenSecret();
      }).toThrow(BadRequestException);
    });
  });
});