/**
 * AdminController 单元测试
 * 
 * 功能描述：
 * - 测试管理员控制器的所有HTTP端点
 * - 验证请求参数处理和响应格式
 * - 测试权限验证和异常处理
 * 
 * 职责分离：
 * - HTTP层测试，不涉及业务逻辑实现
 * - Mock业务服务，专注控制器逻辑
 * - 验证请求响应的正确性
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 创建AdminController测试文件，补充测试覆盖
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2026-01-07
 * @lastModified 2026-01-07
 */

import { Test, TestingModule } from '@nestjs/testing';
import { Response } from 'express';
import { AdminController } from './admin.controller';
import { AdminService } from './admin.service';
import { AdminGuard } from './admin.guard';

describe('AdminController', () => {
  let controller: AdminController;
  let adminService: jest.Mocked<AdminService>;

  const mockAdminService = {
    login: jest.fn(),
    listUsers: jest.fn(),
    getUser: jest.fn(),
    resetPassword: jest.fn(),
    getRuntimeLogs: jest.fn(),
    getLogDirAbsolutePath: jest.fn(),
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [AdminController],
      providers: [
        {
          provide: AdminService,
          useValue: mockAdminService,
        },
      ],
    })
      .overrideGuard(AdminGuard)
      .useValue({ canActivate: () => true })
      .compile();

    controller = module.get<AdminController>(AdminController);
    adminService = module.get(AdminService);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('login', () => {
    it('should login admin successfully', async () => {
      const loginDto = { identifier: 'admin', password: 'Admin123456' };
      const expectedResult = {
        success: true,
        data: { admin: { id: '1', username: 'admin', role: 9 }, access_token: 'token' },
        message: '管理员登录成功'
      };

      adminService.login.mockResolvedValue(expectedResult);

      const result = await controller.login(loginDto);

      expect(adminService.login).toHaveBeenCalledWith('admin', 'Admin123456');
      expect(result).toEqual(expectedResult);
    });

    it('should handle login failure', async () => {
      const loginDto = { identifier: 'admin', password: 'wrong' };
      const expectedResult = {
        success: false,
        message: '密码错误',
        error_code: 'ADMIN_LOGIN_FAILED'
      };

      adminService.login.mockResolvedValue(expectedResult);

      const result = await controller.login(loginDto);

      expect(result.success).toBe(false);
      expect(result.error_code).toBe('ADMIN_LOGIN_FAILED');
    });
  });

  describe('listUsers', () => {
    it('should list users with default pagination', async () => {
      const expectedResult = {
        success: true,
        data: {
          users: [{ id: '1', username: 'user1' }],
          limit: 100,
          offset: 0
        },
        message: '用户列表获取成功'
      };

      adminService.listUsers.mockResolvedValue(expectedResult);

      const result = await controller.listUsers();

      expect(adminService.listUsers).toHaveBeenCalledWith(100, 0);
      expect(result).toEqual(expectedResult);
    });

    it('should list users with custom pagination', async () => {
      const expectedResult = {
        success: true,
        data: {
          users: [],
          limit: 50,
          offset: 10
        },
        message: '用户列表获取成功'
      };

      adminService.listUsers.mockResolvedValue(expectedResult);

      const result = await controller.listUsers('50', '10');

      expect(adminService.listUsers).toHaveBeenCalledWith(50, 10);
      expect(result).toEqual(expectedResult);
    });
  });

  describe('getUser', () => {
    it('should get user by id', async () => {
      const expectedResult = {
        success: true,
        data: { user: { id: '123', username: 'testuser' } },
        message: '用户信息获取成功'
      };

      adminService.getUser.mockResolvedValue(expectedResult);

      const result = await controller.getUser('123');

      expect(adminService.getUser).toHaveBeenCalledWith(BigInt(123));
      expect(result).toEqual(expectedResult);
    });
  });

  describe('resetPassword', () => {
    it('should reset user password', async () => {
      const resetDto = { newPassword: 'NewPass1234' };
      const expectedResult = {
        success: true,
        message: '密码重置成功'
      };

      adminService.resetPassword.mockResolvedValue(expectedResult);

      const result = await controller.resetPassword('123', resetDto);

      expect(adminService.resetPassword).toHaveBeenCalledWith(BigInt(123), 'NewPass1234');
      expect(result).toEqual(expectedResult);
    });
  });

  describe('getRuntimeLogs', () => {
    it('should get runtime logs with default lines', async () => {
      const expectedResult = {
        success: true,
        data: {
          file: 'app.log',
          updated_at: '2026-01-07T00:00:00.000Z',
          lines: ['log line 1', 'log line 2']
        },
        message: '运行日志获取成功'
      };

      adminService.getRuntimeLogs.mockResolvedValue(expectedResult);

      const result = await controller.getRuntimeLogs();

      expect(adminService.getRuntimeLogs).toHaveBeenCalledWith(undefined);
      expect(result).toEqual(expectedResult);
    });

    it('should get runtime logs with custom lines', async () => {
      const expectedResult = {
        success: true,
        data: {
          file: 'app.log',
          updated_at: '2026-01-07T00:00:00.000Z',
          lines: ['log line 1']
        },
        message: '运行日志获取成功'
      };

      adminService.getRuntimeLogs.mockResolvedValue(expectedResult);

      const result = await controller.getRuntimeLogs('100');

      expect(adminService.getRuntimeLogs).toHaveBeenCalledWith(100);
      expect(result).toEqual(expectedResult);
    });
  });

  describe('downloadLogsArchive', () => {
    let mockResponse: Partial<Response>;

    beforeEach(() => {
      mockResponse = {
        setHeader: jest.fn(),
        status: jest.fn().mockReturnThis(),
        json: jest.fn(),
        end: jest.fn(),
        headersSent: false,
      };
    });

    it('should handle missing log directory', async () => {
      adminService.getLogDirAbsolutePath.mockReturnValue('/nonexistent/logs');

      await controller.downloadLogsArchive(mockResponse as Response);

      expect(mockResponse.status).toHaveBeenCalledWith(404);
      expect(mockResponse.json).toHaveBeenCalledWith({
        success: false,
        message: '日志目录不存在'
      });
    });
  });
});