/**
 * 统一配置管理控制器
 *
 * 功能描述：
 * - 提供统一配置管理的REST API接口
 * - 支持配置查询、同步、状态检查
 * - 提供备份管理功能
 *
 * 架构定位：
 * - 层级：Gateway层（网关层）
 * - 职责：HTTP协议处理、API接口暴露
 * - 依赖：调用Business层的ZulipModule服务
 *
 * 职责分离：
 * - API接口：提供RESTful风格的配置管理接口
 * - 协议处理：处理HTTP请求和响应
 * - 参数验证：验证请求参数格式
 * - 错误转换：将业务异常转换为HTTP响应
 *
 * 最近修改：
 * - 2026-01-14: 架构优化 - 从Business层迁移到Gateway层，符合四层架构规范 (修改者: moyin)
 * - 2026-01-14: 代码规范优化 - 完善文件头注释和职责分离描述 (修改者: moyin)
 * - 2026-01-12: 功能新增 - 初始创建统一配置管理控制器 (修改者: moyin)
 *
 * @author moyin
 * @version 3.0.0
 * @since 2026-01-12
 * @lastModified 2026-01-14
 */

import {
  Controller,
  Get,
  Post,
  Query,
  HttpStatus,
  HttpException,
  Logger,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiQuery,
} from '@nestjs/swagger';
import { DynamicConfigManagerService } from '../../core/zulip_core/services/dynamic_config_manager.service';

@ApiTags('unified-config')
@Controller('api/zulip/config')
export class DynamicConfigController {
  private readonly logger = new Logger(DynamicConfigController.name);

  constructor(
    private readonly configManager: DynamicConfigManagerService,
  ) {}

  /**
   * 获取当前配置
   */
  @Get()
  @ApiOperation({
    summary: '获取当前配置',
    description: '获取当前的统一配置（自动从本地加载，如需最新数据请先调用同步接口）'
  })
  @ApiResponse({
    status: 200,
    description: '配置获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        data: { type: 'object' },
        source: { type: 'string', enum: ['remote', 'local', 'default'] },
        timestamp: { type: 'string' }
      }
    }
  })
  async getCurrentConfig() {
    try {
      this.logger.log('获取当前配置');

      const config = await this.configManager.getConfig();
      const status = this.configManager.getConfigStatus();

      return {
        success: true,
        data: config,
        source: config.source || 'unknown',
        lastSyncTime: status.lastSyncTime,
        mapCount: status.mapCount,
        objectCount: status.objectCount,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取配置失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 获取配置状态
   */
  @Get('status')
  @ApiOperation({
    summary: '获取配置状态',
    description: '获取统一配置管理器的状态信息'
  })
  @ApiResponse({
    status: 200,
    description: '状态获取成功'
  })
  async getConfigStatus() {
    try {
      const status = this.configManager.getConfigStatus();

      return {
        success: true,
        data: {
          ...status,
          lastSyncTimeAgo: status.lastSyncTime ?
            Math.round((Date.now() - status.lastSyncTime.getTime()) / 60000) : null,
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取配置状态失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 测试Zulip连接
   */
  @Get('test-connection')
  @ApiOperation({
    summary: '测试Zulip连接',
    description: '测试与Zulip服务器的连接状态'
  })
  @ApiResponse({
    status: 200,
    description: '连接测试完成'
  })
  async testConnection() {
    try {
      this.logger.log('测试Zulip连接');

      const connected = await this.configManager.testZulipConnection();

      return {
        success: true,
        data: {
          connected,
          message: connected ? 'Zulip连接正常' : 'Zulip连接失败'
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('连接测试失败', {
        error: (error as Error).message,
      });

      return {
        success: false,
        data: {
          connected: false,
          message: '连接测试异常'
        },
        error: (error as Error).message,
        timestamp: new Date().toISOString()
      };
    }
  }

  /**
   * 同步远程配置
   */
  @Post('sync')
  @ApiOperation({
    summary: '同步远程配置',
    description: '手动触发从Zulip服务器同步配置到本地文件'
  })
  @ApiResponse({
    status: 200,
    description: '配置同步完成'
  })
  async syncConfig() {
    try {
      this.logger.log('手动同步配置');

      const result = await this.configManager.syncConfig();

      return {
        success: result.success,
        data: {
          source: result.source,
          mapCount: result.mapCount,
          objectCount: result.objectCount,
          lastUpdated: result.lastUpdated,
          backupCreated: result.backupCreated,
          message: result.success ? '配置同步成功' : '配置同步失败'
        },
        error: result.error,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('同步配置失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 获取Stream列表
   */
  @Get('streams')
  @ApiOperation({
    summary: '获取Zulip Stream列表',
    description: '直接从Zulip服务器获取Stream列表'
  })
  @ApiResponse({
    status: 200,
    description: 'Stream列表获取成功'
  })
  async getStreams() {
    try {
      this.logger.log('获取Zulip Stream列表');

      const streams = await this.configManager.getZulipStreams();

      return {
        success: true,
        data: {
          streams: streams.map(stream => ({
            id: stream.stream_id,
            name: stream.name,
            description: stream.description,
            isPublic: !stream.invite_only,
            isWebPublic: stream.is_web_public
          })),
          count: streams.length
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取Stream列表失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 获取指定Stream的Topic列表
   */
  @Get('topics')
  @ApiOperation({
    summary: '获取Stream的Topic列表',
    description: '获取指定Stream的所有Topic'
  })
  @ApiQuery({
    name: 'streamId',
    description: 'Stream ID',
    required: true,
    type: 'number'
  })
  @ApiResponse({
    status: 200,
    description: 'Topic列表获取成功'
  })
  async getTopics(@Query('streamId') streamId: string) {
    try {
      const streamIdNum = parseInt(streamId, 10);
      if (isNaN(streamIdNum)) {
        throw new Error('无效的Stream ID');
      }

      this.logger.log('获取Stream Topic列表', { streamId: streamIdNum });

      const topics = await this.configManager.getZulipTopics(streamIdNum);

      return {
        success: true,
        data: {
          streamId: streamIdNum,
          topics: topics.map(topic => ({
            name: topic.name,
            lastMessageId: topic.max_id
          })),
          count: topics.length
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取Topic列表失败', {
        streamId,
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 查询地图配置
   */
  @Get('maps')
  @ApiOperation({
    summary: '获取地图配置列表',
    description: '获取所有地图的配置信息'
  })
  @ApiResponse({
    status: 200,
    description: '地图配置获取成功'
  })
  async getMaps() {
    try {
      this.logger.log('获取地图配置列表');

      const maps = await this.configManager.getAllMapConfigs();

      return {
        success: true,
        data: {
          maps: maps.map(map => ({
            mapId: map.mapId,
            mapName: map.mapName,
            zulipStream: map.zulipStream,
            zulipStreamId: map.zulipStreamId,
            description: map.description,
            isPublic: map.isPublic,
            objectCount: map.interactionObjects?.length || 0
          })),
          count: maps.length
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取地图配置失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 根据地图ID获取Stream
   */
  @Get('map-to-stream')
  @ApiOperation({
    summary: '地图ID转Stream名称',
    description: '根据地图ID获取对应的Zulip Stream名称'
  })
  @ApiQuery({
    name: 'mapId',
    description: '地图ID',
    required: true,
    type: 'string'
  })
  @ApiResponse({
    status: 200,
    description: '转换成功'
  })
  async mapToStream(@Query('mapId') mapId: string) {
    try {
      this.logger.log('地图ID转Stream', { mapId });

      const streamName = await this.configManager.getStreamByMap(mapId);

      return {
        success: true,
        data: {
          mapId,
          streamName,
          found: !!streamName
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('地图ID转Stream失败', {
        mapId,
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 根据Stream名称获取地图ID
   */
  @Get('stream-to-map')
  @ApiOperation({
    summary: 'Stream名称转地图ID',
    description: '根据Zulip Stream名称获取对应的地图ID'
  })
  @ApiQuery({
    name: 'streamName',
    description: 'Stream名称',
    required: true,
    type: 'string'
  })
  @ApiResponse({
    status: 200,
    description: '转换成功'
  })
  async streamToMap(@Query('streamName') streamName: string) {
    try {
      this.logger.log('Stream转地图ID', { streamName });

      const mapId = await this.configManager.getMapIdByStream(streamName);

      return {
        success: true,
        data: {
          streamName,
          mapId,
          found: !!mapId
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('Stream转地图ID失败', {
        streamName,
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 获取备份文件列表
   */
  @Get('backups')
  @ApiOperation({
    summary: '获取备份文件列表',
    description: '获取所有配置备份文件的列表'
  })
  @ApiResponse({
    status: 200,
    description: '备份列表获取成功'
  })
  async getBackups() {
    try {
      this.logger.log('获取备份文件列表');

      const backups = this.configManager.getBackupFiles();

      return {
        success: true,
        data: {
          backups: backups.map(backup => ({
            name: backup.name,
            size: backup.size,
            created: backup.created,
            sizeKB: Math.round(backup.size / 1024)
          })),
          count: backups.length
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('获取备份列表失败', {
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }

  /**
   * 从备份恢复配置
   */
  @Post('restore')
  @ApiOperation({
    summary: '从备份恢复配置',
    description: '从指定的备份文件恢复配置'
  })
  @ApiQuery({
    name: 'backupFile',
    description: '备份文件名',
    required: true,
    type: 'string'
  })
  @ApiResponse({
    status: 200,
    description: '配置恢复完成'
  })
  async restoreFromBackup(@Query('backupFile') backupFile: string) {
    try {
      this.logger.log('从备份恢复配置', { backupFile });

      const success = await this.configManager.restoreFromBackup(backupFile);

      return {
        success,
        data: {
          backupFile,
          message: success ? '配置恢复成功' : '配置恢复失败'
        },
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('配置恢复失败', {
        backupFile,
        error: (error as Error).message,
      });

      throw new HttpException(
        {
          success: false,
          error: (error as Error).message,
          timestamp: new Date().toISOString()
        },
        HttpStatus.INTERNAL_SERVER_ERROR
      );
    }
  }
}