/**
 * 错误处理属性测试
 * 
 * Property 9: 错误处理标准化
 * 
 * Validates: Requirements 4.6
 * 
 * 测试目标：
 * - 验证错误处理的标准化和一致性
 * - 确保错误响应格式统一
 * - 验证不同类型错误的正确处理
 * 
 * 最近修改：
 * - 2026-01-08: 注释规范优化 - 修正@author字段，更新版本号和修改记录 (修改者: moyin)
 * - 2026-01-08: 功能新增 - 创建错误处理属性测试 (修改者: 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: 错误处理功能', () => {
  let app: INestApplication;
  let module: TestingModule;
  let controller: AdminDatabaseController;
  let mockUsersService: any;
  let mockUserProfilesService: any;
  let mockZulipAccountsService: any;

  beforeAll(async () => {
    mockUsersService = {
      findAll: jest.fn(),
      findOne: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
      remove: jest.fn(),
      search: jest.fn(),
      count: jest.fn()
    };

    mockUserProfilesService = {
      findAll: jest.fn(),
      findOne: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
      remove: jest.fn(),
      findByMap: jest.fn(),
      count: jest.fn()
    };

    mockZulipAccountsService = {
      findMany: jest.fn(),
      findById: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
      delete: jest.fn(),
      batchUpdateStatus: jest.fn().mockResolvedValue({ success: true, updatedCount: 0 }),
      getStatusStatistics: jest.fn()
    };

    module = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath: ['.env.test', '.env']
        })
      ],
      controllers: [AdminDatabaseController],
      providers: [
        DatabaseManagementService,
        {
          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())
          }
        },
        {
          provide: 'UsersService',
          useValue: mockUsersService
        },
        {
          provide: 'IUserProfilesService',
          useValue: mockUserProfilesService
        },
        {
          provide: 'ZulipAccountsService',
          useValue: mockZulipAccountsService
        }
      ]
    })
    .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 9: 错误处理标准化', () => {
    it('数据库连接错误应该返回标准化错误响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '数据库连接错误标准化',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 模拟数据库连接错误
          mockUsersService.create.mockRejectedValueOnce(
            new Error('Connection timeout')
          );

          try {
            const response = await controller.createUser({
              ...userData,
              status: UserStatus.ACTIVE
            });
            
            // 如果没有抛出异常，验证错误响应格式
            if (!response.success) {
              expect(response).toHaveProperty('success', false);
              expect(response).toHaveProperty('message');
              expect(response).toHaveProperty('error_code');
              expect(response).toHaveProperty('timestamp');
              expect(response).toHaveProperty('request_id');
              
              expect(typeof response.message).toBe('string');
              expect(typeof response.error_code).toBe('string');
              expect(typeof response.timestamp).toBe('string');
              expect(typeof response.request_id).toBe('string');
            }
          } catch (error) {
            // 如果抛出异常，验证异常被正确处理
            expect(error).toBeDefined();
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 }
      );
    });

    it('资源不存在错误应该返回一致的404响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '资源不存在错误一致性',
        () => ({
          entityType: ['User', 'UserProfile', 'ZulipAccount'][Math.floor(Math.random() * 3)],
          entityId: `nonexistent_${Math.floor(Math.random() * 1000)}`
        }),
        async ({ entityType, entityId }) => {
          // 模拟资源不存在
          if (entityType === 'User') {
            mockUsersService.findOne.mockResolvedValueOnce(null);
          } else if (entityType === 'UserProfile') {
            mockUserProfilesService.findOne.mockResolvedValueOnce(null);
          } else {
            mockZulipAccountsService.findById.mockResolvedValueOnce(null);
          }

          try {
            let response;
            if (entityType === 'User') {
              response = await controller.getUserById(entityId);
            } else if (entityType === 'UserProfile') {
              response = await controller.getUserProfileById(entityId);
            } else {
              response = await controller.getZulipAccountById(entityId);
            }
            
            // 验证404错误响应格式
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('NOT_FOUND');
              expect(response.message).toContain('not found');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
            }
          } catch (error: any) {
            // 验证异常包含正确信息
            expect(error.message).toContain('not found');
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 25 }
      );
    });

    it('数据验证错误应该返回详细的错误信息', async () => {
      await PropertyTestRunner.runPropertyTest(
        '数据验证错误详细信息',
        () => {
          const invalidData = {
            username: '', // 空用户名
            email: 'invalid-email', // 无效邮箱格式
            role: -1, // 无效角色
            status: 'INVALID_STATUS' as any // 无效状态
          };
          
          return invalidData;
        },
        async (invalidData) => {
          // 模拟验证错误
          mockUsersService.create.mockRejectedValueOnce(
            new Error('Validation failed: username is required, email format invalid')
          );

          try {
            const response = await controller.createUser({
              ...invalidData,
              nickname: 'Test Nickname' // 添加必需的nickname字段
            });
            
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('VALIDATION');
              expect(response.message).toContain('validation');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
              
              // 验证错误信息包含具体字段
              expect(response.message.toLowerCase()).toMatch(/(username|email|role|status)/);
            }
          } catch (error: any) {
            expect(error.message).toContain('validation');
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 }
      );
    });

    it('权限不足错误应该返回标准化403响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '权限不足错误标准化',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 模拟权限不足错误
          mockUsersService.create.mockRejectedValueOnce(
            new Error('Insufficient permissions')
          );

          try {
            const response = await controller.createUser({
              ...userData,
              status: UserStatus.ACTIVE
            });
            
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('FORBIDDEN');
              expect(response.message).toContain('permission');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
            }
          } catch (error: any) {
            expect(error.message).toContain('permission');
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 }
      );
    });

    it('并发冲突错误应该返回适当的错误响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '并发冲突错误处理',
        () => ({
          user: PropertyTestGenerators.generateUser(),
          conflictType: ['duplicate_key', 'version_conflict', 'resource_locked'][
            Math.floor(Math.random() * 3)
          ]
        }),
        async ({ user, conflictType }) => {
          // 模拟不同类型的并发冲突
          let errorMessage;
          switch (conflictType) {
            case 'duplicate_key':
              errorMessage = 'Duplicate key violation: username already exists';
              break;
            case 'version_conflict':
              errorMessage = 'Version conflict: resource was modified by another user';
              break;
            case 'resource_locked':
              errorMessage = 'Resource is locked by another operation';
              break;
          }
          
          mockUsersService.create.mockRejectedValueOnce(new Error(errorMessage));

          try {
            const response = await controller.createUser({
              ...user,
              status: UserStatus.ACTIVE
            });
            
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('CONFLICT');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
              
              // 验证错误信息反映冲突类型
              if (conflictType === 'duplicate_key') {
                expect(response.message).toContain('duplicate');
              } else if (conflictType === 'version_conflict') {
                expect(response.message).toContain('conflict');
              } else {
                expect(response.message).toContain('locked');
              }
            }
          } catch (error: any) {
            expect(error.message).toBe(errorMessage);
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 }
      );
    });

    it('系统内部错误应该返回通用错误响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '系统内部错误处理',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 模拟系统内部错误
          mockUsersService.create.mockRejectedValueOnce(
            new Error('Internal system error: unexpected null pointer')
          );

          try {
            const response = await controller.createUser({
              ...userData,
              status: UserStatus.ACTIVE
            });
            
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('INTERNAL_ERROR');
              expect(response.message).toContain('internal error');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
              
              // 内部错误不应该暴露敏感信息
              expect(response.message).not.toContain('null pointer');
              expect(response.message).not.toContain('stack trace');
            }
          } catch (error: any) {
            // 如果抛出异常，验证异常被适当处理
            expect(error).toBeDefined();
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 }
      );
    });

    it('网络超时错误应该返回适当的错误响应', async () => {
      await PropertyTestRunner.runPropertyTest(
        '网络超时错误处理',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 模拟网络超时错误
          const timeoutError = new Error('Request timeout');
          timeoutError.name = 'TimeoutError';
          mockUsersService.create.mockRejectedValueOnce(timeoutError);

          try {
            const response = await controller.createUser({
              ...userData,
              status: UserStatus.ACTIVE
            });
            
            if (!response.success) {
              expect(response.success).toBe(false);
              expect(response.error_code).toContain('TIMEOUT');
              expect(response.message).toContain('timeout');
              PropertyTestAssertions.assertApiResponseFormat(response, false);
            }
          } catch (error: any) {
            expect(error.message).toContain('timeout');
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 }
      );
    });

    it('错误响应应该包含有用的调试信息', async () => {
      await PropertyTestRunner.runPropertyTest(
        '错误调试信息完整性',
        () => PropertyTestGenerators.generateUser(),
        async (userData) => {
          // 模拟带详细信息的错误
          mockUsersService.create.mockRejectedValueOnce(
            new Error('Database constraint violation: unique_username_constraint')
          );

          try {
            const response = await controller.createUser({
              ...userData,
              status: UserStatus.ACTIVE
            });
            
            if (!response.success) {
              PropertyTestAssertions.assertApiResponseFormat(response, false);
              
              // 验证调试信息
              expect(response.timestamp).toBeDefined();
              expect(response.request_id).toBeDefined();
              expect(response.error_code).toBeDefined();
              
              // 验证时间戳格式
              const timestamp = new Date(response.timestamp);
              expect(timestamp.toISOString()).toBe(response.timestamp);
              
              // 验证请求ID格式
              expect(response.request_id).toMatch(/^[a-zA-Z0-9_-]+$/);
              
              // 验证错误码格式
              expect(response.error_code).toMatch(/^[A-Z_]+$/);
            }
          } catch (error: any) {
            expect(error).toBeDefined();
          }
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 20 }
      );
    });

    it('批量操作中的部分错误应该被正确处理', async () => {
      await PropertyTestRunner.runPropertyTest(
        '批量操作部分错误处理',
        () => {
          const accountIds = Array.from({ length: Math.floor(Math.random() * 5) + 3 }, 
            (_, i) => `account_${i + 1}`);
          const targetStatus = 'active' as const;
          
          return { accountIds, targetStatus };
        },
        async ({ accountIds, targetStatus }) => {
          // 模拟部分成功，部分失败的批量操作
          accountIds.forEach((id, index) => {
            if (index === 0) {
              // 第一个操作失败
              mockZulipAccountsService.update.mockRejectedValueOnce(
                new Error(`Failed to update account ${id}: validation error`)
              );
            } else {
              // 其他操作成功
              mockZulipAccountsService.update.mockResolvedValueOnce({
                id,
                status: targetStatus,
                ...PropertyTestGenerators.generateZulipAccount()
              });
            }
          });

          const response = await controller.batchUpdateZulipAccountStatus({
            ids: accountIds,
            status: targetStatus,
            reason: '测试批量更新'
          });

          expect(response.success).toBe(true); // 批量操作本身成功
          expect(response.data.failed).toBe(1); // 一个失败
          expect(response.data.success).toBe(accountIds.length - 1); // 其他成功
          
          // 验证错误信息格式
          expect(response.data.errors).toHaveLength(1);
          expect(response.data.errors[0]).toHaveProperty('id');
          expect(response.data.errors[0]).toHaveProperty('success', false);
          expect(response.data.errors[0]).toHaveProperty('error');
          
          PropertyTestAssertions.assertApiResponseFormat(response, true);
        },
        { ...DEFAULT_PROPERTY_CONFIG, iterations: 15 }
      );
    });
  });
});