import { Controller, Get, Post, Delete, Body, Param, Query, Req, Logger, BadRequestException } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiQuery, ApiParam } from '@nestjs/swagger';
import { ConfigService } from '@nestjs/config';
import { ConfigManagementService } from '../../application/services/config.service';
import { Public } from '../../shared/guards/admin-auth.guard';
import { getClientIp } from '../../shared/utils/get-client-ip';

class SetConfigDto { category: string; key: string; value: string; description?: string; }

@ApiTags('Config')
@ApiBearerAuth()
@Controller('configs')
export class ConfigController {
  private readonly logger = new Logger(ConfigController.name);

  constructor(
    private readonly configService: ConfigManagementService,
    private readonly appConfigService: ConfigService,
  ) {}

  @Get()
  @ApiOperation({ summary: '获取配置列表' })
  @ApiQuery({ name: 'category', required: false })
  async getConfigs(@Query('category') category?: string) {
    return this.configService.getConfigs(category);
  }

  @Get('transfer-enabled')
  @ApiOperation({ summary: '获取划转开关状态' })
  async getTransferEnabled() {
    const config = await this.configService.getConfig('system', 'transfer_enabled');
    return { enabled: config?.value === 'true' };
  }

  @Post('transfer-enabled')
  @ApiOperation({ summary: '设置划转开关状态' })
  async setTransferEnabled(@Body() body: { enabled: boolean }, @Req() req: any) {
    await this.configService.setConfig(req.admin.id, 'system', 'transfer_enabled', String(body.enabled), '划转开关', getClientIp(req), req.headers['user-agent']);
    return { success: true };
  }

  @Get('mining/status')
  @ApiOperation({ summary: '获取挖矿状态' })
  async getMiningStatus() {
    const miningServiceUrl = this.appConfigService.get<string>('MINING_SERVICE_URL', 'http://localhost:3021');
    const contributionServiceUrl = this.appConfigService.get<string>('CONTRIBUTION_SERVICE_URL', 'http://localhost:3020');

    this.logger.log(`Fetching mining status from ${miningServiceUrl}/api/v2/mining/admin/status`);
    try {
      // 并行获取 mining-service 状态和 contribution-service 统计数据
      const [miningResponse, contributionResponse] = await Promise.all([
        fetch(`${miningServiceUrl}/api/v2/mining/admin/status`),
        fetch(`${contributionServiceUrl}/api/v2/contribution/stats`).catch(() => null),
      ]);

      if (!miningResponse.ok) {
        throw new Error(`Failed to fetch mining status: ${miningResponse.status}`);
      }
      const miningResult = await miningResponse.json();
      this.logger.log(`Mining service response: ${JSON.stringify(miningResult)}`);

      const miningData = miningResult.data || miningResult;

      // 获取 contribution-service 的全网理论算力
      let networkTotalContribution: string | null = null;
      let userEffectiveContribution: string | null = null;
      let systemAccountsContribution: string | null = null;
      let unprocessedAdoptions = -1;

      if (contributionResponse && contributionResponse.ok) {
        const contributionResult = await contributionResponse.json();
        const data = contributionResult.data || contributionResult;

        // 全网理论算力 = 总认种树 × 每棵树算力
        networkTotalContribution = data.networkTotalContribution || null;
        // 用户有效算力
        userEffectiveContribution = data.totalContribution || null;
        // 未处理认种数
        unprocessedAdoptions = data.unprocessedAdoptions ?? -1;
        // 系统账户算力
        const systemAccounts = data.systemAccounts || [];
        const systemTotal = systemAccounts
          .filter((a: any) => a.accountType !== 'HEADQUARTERS')
          .reduce((sum: number, a: any) => sum + parseFloat(a.totalContribution || '0'), 0);
        systemAccountsContribution = systemTotal.toString();
      }

      // mining-service 中的全网理论算力
      const miningNetworkTotal = miningData.networkTotalContribution || '0';
      // mining-service 中的用户有效算力
      const miningUserTotal = miningData.totalContribution || '0';

      // 判断算力是否同步完成
      // 条件1：全网理论算力已同步（mining-service 的 networkTotalContribution 与 contribution-service 相近）
      // 全网理论算力是挖矿分母，必须同步后才能正确计算挖矿比例
      const networkSynced = networkTotalContribution !== null &&
        parseFloat(networkTotalContribution) > 0 &&
        parseFloat(miningNetworkTotal) > 0 &&
        Math.abs(parseFloat(miningNetworkTotal) - parseFloat(networkTotalContribution)) / parseFloat(networkTotalContribution) < 0.001;

      // 条件2：所有认种已处理完成（无未分配的认种记录）
      const allAdoptionsProcessed = unprocessedAdoptions === 0;

      const isSynced = networkSynced && allAdoptionsProcessed;

      this.logger.log(
        `[SyncCheck] networkSynced=${networkSynced} (contribution=${networkTotalContribution}, mining=${miningNetworkTotal}), ` +
          `allAdoptionsProcessed=${allAdoptionsProcessed} (unprocessedAdoptions=${unprocessedAdoptions}), ` +
          `isSynced=${isSynced}`,
      );

      return {
        ...miningData,
        contributionSyncStatus: {
          isSynced,
          // 全网理论算力（应作为挖矿分母）
          networkTotalContribution: networkTotalContribution || '0',
          miningNetworkTotal,
          // 用户有效算力
          userEffectiveContribution: userEffectiveContribution || '0',
          miningUserTotal,
          // 系统账户算力
          systemAccountsContribution: systemAccountsContribution || '0',
          // 未处理认种数
          unprocessedAdoptions,
          // 兼容旧字段
          miningTotal: miningUserTotal,
          contributionTotal: userEffectiveContribution || '0',
        },
      };
    } catch (error) {
      this.logger.error('Failed to get mining status', error);
      return {
        initialized: false,
        isActive: false,
        error: `Unable to connect to mining service: ${error.message}`,
        contributionSyncStatus: {
          isSynced: false,
          networkTotalContribution: '0',
          miningNetworkTotal: '0',
          userEffectiveContribution: '0',
          miningUserTotal: '0',
          systemAccountsContribution: '0',
          unprocessedAdoptions: -1,
          miningTotal: '0',
          contributionTotal: '0',
        },
      };
    }
  }

  @Post('mining/activate')
  @ApiOperation({ summary: '激活挖矿' })
  async activateMining(@Req() req: any) {
    const miningServiceUrl = this.appConfigService.get<string>('MINING_SERVICE_URL', 'http://localhost:3021');
    const walletServiceUrl = this.appConfigService.get<string>('MINING_WALLET_SERVICE_URL', 'http://localhost:3025');

    // 安全检查：池账户余额不能为0
    try {
      const [poolARes, poolBRes] = await Promise.all([
        fetch(`${walletServiceUrl}/api/v2/pool-accounts/SHARE_POOL_A`),
        fetch(`${walletServiceUrl}/api/v2/pool-accounts/SHARE_POOL_B`),
      ]);
      if (poolARes.ok && poolBRes.ok) {
        const poolA = await poolARes.json();
        const poolB = await poolBRes.json();
        const balA = parseFloat(poolA?.data?.balance ?? poolA?.balance ?? '0');
        const balB = parseFloat(poolB?.data?.balance ?? poolB?.balance ?? '0');
        if (balA <= 0 || balB <= 0) {
          const msg = `池账户余额不足，无法激活挖矿。积分股池A余额: ${balA}，积分股池B余额: ${balB}。请先通过区块链充值。`;
          this.logger.warn(msg);
          throw new BadRequestException(msg);
        }
      } else {
        this.logger.warn('无法获取池账户余额，跳过安全检查');
      }
    } catch (error) {
      if (error instanceof BadRequestException) throw error;
      this.logger.warn('池账户余额检查失败，跳过安全检查', error);
    }

    try {
      const response = await fetch(`${miningServiceUrl}/api/v2/mining/admin/activate`, {
        method: 'POST',
      });
      if (!response.ok) {
        throw new Error('Failed to activate mining');
      }
      const result = await response.json();
      this.logger.log(`Mining activated by admin ${req.admin?.id}`);
      await this.configService.recordAuditLog(req.admin.id, 'ACTIVATE', 'MINING', undefined, undefined, getClientIp(req), req.headers['user-agent']);
      return result;
    } catch (error) {
      if (error instanceof BadRequestException) throw error;
      this.logger.error('Failed to activate mining', error);
      return { success: false, message: 'Failed to activate mining' };
    }
  }

  @Post('mining/deactivate')
  @ApiOperation({ summary: '停用挖矿' })
  async deactivateMining(@Req() req: any) {
    const miningServiceUrl = this.appConfigService.get<string>('MINING_SERVICE_URL', 'http://localhost:3021');
    try {
      const response = await fetch(`${miningServiceUrl}/api/v2/mining/admin/deactivate`, {
        method: 'POST',
      });
      if (!response.ok) {
        throw new Error('Failed to deactivate mining');
      }
      const result = await response.json();
      this.logger.log(`Mining deactivated by admin ${req.admin?.id}`);
      await this.configService.recordAuditLog(req.admin.id, 'DEACTIVATE', 'MINING', undefined, undefined, getClientIp(req), req.headers['user-agent']);
      return result;
    } catch (error) {
      this.logger.error('Failed to deactivate mining', error);
      return { success: false, message: 'Failed to deactivate mining' };
    }
  }

  // ============ P2P 划转手续费配置 ============

  @Get('p2p-transfer-fee')
  @ApiOperation({ summary: '获取P2P划转手续费配置' })
  async getP2pTransferFee() {
    const [feeConfig, minAmountConfig] = await Promise.all([
      this.configService.getConfig('trading', 'p2p_transfer_fee'),
      this.configService.getConfig('trading', 'min_p2p_transfer_amount'),
    ]);
    return {
      fee: feeConfig?.value ?? '5',
      minTransferAmount: minAmountConfig?.value ?? '6',
    };
  }

  @Post('p2p-transfer-fee')
  @ApiOperation({ summary: '设置P2P划转手续费配置' })
  async setP2pTransferFee(
    @Body() body: { fee: string; minTransferAmount: string },
    @Req() req: any,
  ) {
    const fee = parseFloat(body.fee);
    const minAmount = parseFloat(body.minTransferAmount);

    if (isNaN(fee) || fee < 0) {
      throw new BadRequestException('手续费必须 >= 0');
    }
    if (isNaN(minAmount) || minAmount <= fee) {
      throw new BadRequestException('最小划转金额必须大于手续费');
    }

    const ip = getClientIp(req);
    const ua = req.headers['user-agent'];
    await Promise.all([
      this.configService.setConfig(
        req.admin.id, 'trading', 'p2p_transfer_fee',
        body.fee, 'P2P划转手续费(积分值)', ip, ua,
      ),
      this.configService.setConfig(
        req.admin.id, 'trading', 'min_p2p_transfer_amount',
        body.minTransferAmount, 'P2P最小划转金额(积分值)', ip, ua,
      ),
    ]);

    return { success: true };
  }

  @Get('internal/p2p-transfer-fee')
  @Public()
  @ApiOperation({ summary: '获取P2P划转手续费配置（内部调用，无需鉴权）' })
  async getP2pTransferFeeInternal() {
    const [feeConfig, minAmountConfig] = await Promise.all([
      this.configService.getConfig('trading', 'p2p_transfer_fee'),
      this.configService.getConfig('trading', 'min_p2p_transfer_amount'),
    ]);
    return {
      fee: feeConfig?.value ?? '5',
      minTransferAmount: minAmountConfig?.value ?? '6',
    };
  }

  // ============ 通用配置 ============

  @Get(':category/:key')
  @ApiOperation({ summary: '获取单个配置' })
  @ApiParam({ name: 'category' })
  @ApiParam({ name: 'key' })
  async getConfig(@Param('category') category: string, @Param('key') key: string) {
    return this.configService.getConfig(category, key);
  }

  @Post()
  @ApiOperation({ summary: '设置配置' })
  async setConfig(@Body() dto: SetConfigDto, @Req() req: any) {
    await this.configService.setConfig(req.admin.id, dto.category, dto.key, dto.value, dto.description, getClientIp(req), req.headers['user-agent']);
    return { success: true };
  }

  @Delete(':category/:key')
  @ApiOperation({ summary: '删除配置' })
  async deleteConfig(@Param('category') category: string, @Param('key') key: string, @Req() req: any) {
    await this.configService.deleteConfig(req.admin.id, category, key, getClientIp(req), req.headers['user-agent']);
    return { success: true };
  }
}
