/**
 * API响应格式一致性属性测试
 * 
 * Property 7: API响应格式一致性
 * Validates: Requirements 4.1, 4.2, 4.3
 * 
 * 测试目标：
 * - 验证所有API端点返回统一的响应格式
 * - 确保成功和失败响应都符合规范
 * - 验证响应字段类型和必需性
 * 
 * 最近修改：
 * - 2026-01-08: 注释规范优化 - 修正@author字段，更新版本号和修改记录 (修改者: moyin)
 * - 2026-01-08: 功能新增 - 创建API响应格式属性测试 (修改者: assistant)
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2026-01-08
 * @lastModified 2026-01-08
 */

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AdminDatabaseController } from './admin_database.controller';
import { DatabaseManagementService } from './database_management.service';
import { AdminOperationLogService } from './admin_operation_log.service';
import { AdminOperationLogInterceptor } from './admin_operation_log.interceptor';
import { AdminDatabaseExceptionFilter } from './admin_database_exception.filter';
import { AdminGuard } from './admin.guard';
import { UserStatus } from '../user_mgmt/user_status.enum';
import {
  PropertyTestRunner,
  PropertyTestGenerators,
  PropertyTestAssertions,
  DEFAULT_PROPERTY_CONFIG
} from './admin_property_test.base';

describe('Property Test: API响应格式一致性', () => {
  let app: INestApplication;
  let module: TestingModule;
  let controller: AdminDatabaseController;
  let mockDatabaseService: any;

  beforeAll(async () => {
    mockDatabaseService = {
      getUserList: jest.fn().mockImplementation((limit, offset) => {
        return Promise.resolve({
          success: true,
          data: {
            items: [],
            total: 0,
            limit: limit || 20,
            offset: offset || 0,
            has_more: false
          },
          message: '获取用户列表成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getUserById: jest.fn().mockImplementation((id) => {
        const user = PropertyTestGenerators.generateUser();
        return Promise.resolve({
          success: true,
          data: { ...user, id: id.toString() },
          message: '获取用户详情成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      createUser: jest.fn().mockImplementation((userData) => {
        return Promise.resolve({
          success: true,
          data: { ...userData, id: '1' },
          message: '创建用户成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      updateUser: jest.fn().mockImplementation((id, updateData) => {
        const user = PropertyTestGenerators.generateUser();
        return Promise.resolve({
          success: true,
          data: { ...user, ...updateData, id: id.toString() },
          message: '更新用户成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      deleteUser: jest.fn().mockImplementation((id) => {
        return Promise.resolve({
          success: true,
          data: { deleted: true, id: id.toString() },
          message: '删除用户成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      searchUsers: jest.fn().mockImplementation((searchTerm, limit) => {
        return Promise.resolve({
          success: true,
          data: {
            items: [],
            total: 0,
            limit: limit || 20,
            offset: 0,
            has_more: false
          },
          message: '搜索用户成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getUserProfileList: jest.fn().mockImplementation((limit, offset) => {
        return Promise.resolve({
          success: true,
          data: {
            items: [],
            total: 0,
            limit: limit || 20,
            offset: offset || 0,
            has_more: false
          },
          message: '获取用户档案列表成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getUserProfileById: jest.fn().mockImplementation((id) => {
        const profile = PropertyTestGenerators.generateUserProfile();
        return Promise.resolve({
          success: true,
          data: { ...profile, id: id.toString() },
          message: '获取用户档案详情成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getUserProfilesByMap: jest.fn().mockImplementation((map, limit, offset) => {
        return Promise.resolve({
          success: true,
          data: {
            items: [],
            total: 0,
            limit: limit || 20,
            offset: offset || 0,
            has_more: false
          },
          message: '按地图获取用户档案成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getZulipAccountList: jest.fn().mockImplementation((limit, offset) => {
        return Promise.resolve({
          success: true,
          data: {
            items: [],
            total: 0,
            limit: limit || 20,
            offset: offset || 0,
            has_more: false
          },
          message: '获取Zulip账号列表成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getZulipAccountById: jest.fn().mockImplementation((id) => {
        const account = PropertyTestGenerators.generateZulipAccount();
        return Promise.resolve({
          success: true,
          data: { ...account, id: id.toString() },
          message: '获取Zulip账号详情成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      }),
      getZulipAccountStatistics: jest.fn().mockImplementation(() => {
        return Promise.resolve({
          success: true,
          data: {
            active: 0,
            inactive: 0,
            suspended: 0,
            error: 0,
            total: 0
          },
          message: '获取Zulip账号统计成功',
          timestamp: new Date().toISOString(),
          request_id: 'test_' + Date.now()
        });
      })
    };

    module = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath: ['.env.test', '.env']
        })
      ],
      controllers: [AdminDatabaseController],
      providers: [
        {
          provide: DatabaseManagementService,
          useValue: mockDatabaseService
        },
        {
          provide: AdminOperationLogService,
          useValue: {
            createLog: jest.fn().mockResolvedValue({}),
            queryLogs: jest.fn().mockResolvedValue({ logs: [], total: 0 }),
            getLogById: jest.fn().mockResolvedValue(null),
            getStatistics: jest.fn().mockResolvedValue({}),
            cleanupExpiredLogs: jest.fn().mockResolvedValue(0),
            getAdminOperationHistory: jest.fn().mockResolvedValue([]),
            getSensitiveOperations: jest.fn().mockResolvedValue({ logs: [], total: 0 })
          }
        },
        {
          provide: AdminOperationLogInterceptor,
          useValue: {
            intercept: jest.fn().mockImplementation((context, next) => next.handle())
          }
        }
      ]
    })
    .overrideGuard(AdminGuard)
    .useValue({ canActivate: () => true })
    .compile();

    app = module.createNestApplication();
    app.useGlobalFilters(new AdminDatabaseExceptionFilter());
    await app.init();

    controller = module.get<AdminDatabaseController>(AdminDatabaseController);
  });

  afterAll(async () => {
    await app.close();
  });

  describe('Property 7: API响应格式一致性', () => {
    it('所有成功响应应该有统一的格式', async () => {
      await PropertyTestRunner.runPropertyTest(
        'API成功响应格式一致性',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 测试用户管理端点
          const userListResponse = await controller.getUserList(20, 0);
          PropertyTestAssertions.assertListResponseFormat(userListResponse);

          const userDetailResponse = await controller.getUserById('1');
          PropertyTestAssertions.assertApiResponseFormat(userDetailResponse, true);

          const createUserResponse = await controller.createUser({
            ...userData,
            status: UserStatus.ACTIVE
          });
          PropertyTestAssertions.assertApiResponseFormat(createUserResponse, true);

          // 测试用户档案管理端点
          const profileListResponse = await controller.getUserProfileList(20, 0);
          PropertyTestAssertions.assertListResponseFormat(profileListResponse);

          const profileDetailResponse = await controller.getUserProfileById('1');
          PropertyTestAssertions.assertApiResponseFormat(profileDetailResponse, true);

          // 测试Zulip账号管理端点
          const zulipListResponse = await controller.getZulipAccountList(20, 0);
          PropertyTestAssertions.assertListResponseFormat(zulipListResponse);

          const zulipDetailResponse = await controller.getZulipAccountById('1');
          PropertyTestAssertions.assertApiResponseFormat(zulipDetailResponse, true);

          const zulipStatsResponse = await controller.getZulipAccountStatistics();
          PropertyTestAssertions.assertApiResponseFormat(zulipStatsResponse, true);

          // 测试系统端点
          const healthResponse = await controller.healthCheck();
          PropertyTestAssertions.assertApiResponseFormat(healthResponse, true);
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 50 }
      );
    });

    it('所有列表响应应该有正确的分页信息', async () => {
      await PropertyTestRunner.runPropertyTest(
        '列表响应分页格式一致性',
        () => PropertyTestGenerators.generatePaginationParams(),
        async (paginationParams) => {
          const { limit, offset } = paginationParams;
          
          // 限制参数范围以避免无效请求
          const safeLimit = Math.min(Math.max(limit, 1), 100);
          const safeOffset = Math.max(offset, 0);

          // 测试所有列表端点
          const userListResponse = await controller.getUserList(safeLimit, safeOffset);
          PropertyTestAssertions.assertPaginationLogic(userListResponse, safeLimit, safeOffset);

          const profileListResponse = await controller.getUserProfileList(safeLimit, safeOffset);
          PropertyTestAssertions.assertPaginationLogic(profileListResponse, safeLimit, safeOffset);

          const zulipListResponse = await controller.getZulipAccountList(safeLimit, safeOffset);
          PropertyTestAssertions.assertPaginationLogic(zulipListResponse, safeLimit, safeOffset);

          const mapProfilesResponse = await controller.getUserProfilesByMap('plaza', safeLimit, safeOffset);
          PropertyTestAssertions.assertPaginationLogic(mapProfilesResponse, safeLimit, safeOffset);
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 30 }
      );
    });

    it('响应时间戳应该是有效的ISO格式', async () => {
      await PropertyTestRunner.runPropertyTest(
        '响应时间戳格式验证',
        () => ({}),
        async () => {
          const response = await controller.healthCheck();
          
          expect(response.timestamp).toBeDefined();
          expect(typeof response.timestamp).toBe('string');
          
          // 验证ISO 8601格式
          const timestamp = new Date(response.timestamp);
          expect(timestamp.toISOString()).toBe(response.timestamp);
          
          // 验证时间戳是最近的（在过去1分钟内）
          const now = new Date();
          const timeDiff = now.getTime() - timestamp.getTime();
          expect(timeDiff).toBeLessThan(60000); // 1分钟
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 }
      );
    });

    it('请求ID应该是唯一的', async () => {
      const requestIds = new Set<string>();
      
      await PropertyTestRunner.runPropertyTest(
        '请求ID唯一性验证',
        () => ({}),
        async () => {
          const response = await controller.healthCheck();
          
          expect(response.request_id).toBeDefined();
          expect(typeof response.request_id).toBe('string');
          expect(response.request_id.length).toBeGreaterThan(0);
          
          // 验证请求ID唯一性
          expect(requestIds.has(response.request_id)).toBe(false);
          requestIds.add(response.request_id);
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 100 }
      );
    });
  });
});