import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Decimal } from 'decimal.js';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

// 基准算力常量
const BASE_CONTRIBUTION_PER_TREE = new Decimal('22617');
const RATE_PERSONAL = new Decimal('0.70');
const RATE_OPERATION = new Decimal('0.12');
const RATE_PROVINCE = new Decimal('0.01');
const RATE_CITY = new Decimal('0.02');
const RATE_LEVEL_TOTAL = new Decimal('0.075');
const RATE_BONUS_TOTAL = new Decimal('0.075');

// 远程服务数据缓存
interface RemoteServiceData {
  totalDistributed: string;
  totalBurned: string;
  circulationPool: string;
  fetchedAt: Date;
}

@Injectable()
export class DashboardService {
  private readonly logger = new Logger(DashboardService.name);
  private remoteDataCache: RemoteServiceData | null = null;
  private readonly CACHE_TTL_MS = 30000; // 30秒缓存

  constructor(
    private readonly prisma: PrismaService,
    private readonly configService: ConfigService,
  ) {}

  /**
   * 获取仪表盘统计数据
   * 优先从本地同步表获取，如果没有数据则调用远程服务
   */
  async getDashboardStats(): Promise<any> {
    const [
      userStats,
      contributionStats,
      miningStats,
      tradingStats,
      latestReport,
      latestKLine,
      detailedContributionStats,
      remoteData,
    ] = await Promise.all([
      this.getUserStats(),
      this.getContributionStats(),
      this.getMiningStats(),
      this.getTradingStats(),
      this.prisma.dailyReport.findFirst({ orderBy: { reportDate: 'desc' } }),
      this.prisma.syncedDayKLine.findFirst({ orderBy: { klineDate: 'desc' } }),
      this.getDetailedContributionStats(),
      this.fetchRemoteServiceData(),
    ]);

    // 合并远程服务数据（如果本地数据为空或为0则使用远程数据）
    const totalMined = miningStats.totalMined !== '0'
      ? miningStats.totalMined
      : remoteData.totalDistributed;

    const totalBurned = miningStats.latestDailyStat?.totalBurned || remoteData.totalBurned;

    const circulationPoolShares = tradingStats.circulationPool?.totalShares !== '0'
      ? tradingStats.circulationPool?.totalShares
      : remoteData.circulationPool;

    return {
      users: userStats,
      contribution: contributionStats,
      mining: {
        ...miningStats,
        totalMined, // 使用合并后的已分配数据
      },
      trading: {
        ...tradingStats,
        circulationPool: {
          totalShares: circulationPoolShares || '0',
          totalCash: tradingStats.circulationPool?.totalCash || '0',
        },
      },
      // 直接提供远程数据用于仪表盘显示
      remoteData: {
        totalDistributed: remoteData.totalDistributed,
        totalBurned: remoteData.totalBurned,
        circulationPool: remoteData.circulationPool,
      },
      detailedContribution: detailedContributionStats,
      latestReport: latestReport
        ? this.formatDailyReport(latestReport)
        : null,
      latestPrice: latestKLine
        ? {
            date: latestKLine.klineDate,
            open: latestKLine.open.toString(),
            high: latestKLine.high.toString(),
            low: latestKLine.low.toString(),
            close: latestKLine.close.toString(),
            volume: latestKLine.volume.toString(),
            amount: latestKLine.amount.toString(),
          }
        : null,
      timestamp: new Date().toISOString(),
    };
  }

  /**
   * 获取实时数据
   */
  async getRealtimeStats(): Promise<any> {
    const [miningConfig, circulationPool, latestKLine] = await Promise.all([
      this.prisma.syncedMiningConfig.findFirst(),
      this.prisma.syncedCirculationPool.findFirst(),
      this.prisma.syncedDayKLine.findFirst({ orderBy: { klineDate: 'desc' } }),
    ]);

    return {
      miningActive: miningConfig?.isActive || false,
      currentEra: miningConfig?.currentEra || 0,
      minuteDistribution: miningConfig?.minuteDistribution?.toString() || '0',
      remainingDistribution:
        miningConfig?.remainingDistribution?.toString() || '0',
      circulationShares: circulationPool?.totalShares?.toString() || '0',
      circulationCash: circulationPool?.totalCash?.toString() || '0',
      currentPrice: latestKLine?.close?.toString() || '1',
      timestamp: new Date().toISOString(),
    };
  }

  /**
   * 获取用户统计
   */
  private async getUserStats() {
    const [totalUsers, activeUsers, kycVerifiedUsers, adoptedUsers] =
      await Promise.all([
        this.prisma.syncedUser.count(),
        this.prisma.syncedUser.count({ where: { status: 'ACTIVE' } }),
        this.prisma.syncedUser.count({ where: { kycStatus: 'VERIFIED' } }),
        this.prisma.syncedContributionAccount.count({
          where: { hasAdopted: true },
        }),
      ]);

    // 今日新增用户
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const newUsersToday = await this.prisma.syncedUser.count({
      where: { createdAt: { gte: today } },
    });

    return {
      total: totalUsers,
      active: activeUsers,
      kycVerified: kycVerifiedUsers,
      adopted: adoptedUsers,
      newToday: newUsersToday,
    };
  }

  /**
   * 获取算力统计
   *
   * 有效算力 = 个人算力(70%) + 运营账户(12%) + 省公司(1%) + 市公司(2%)
   *          + 已解锁层级 + 未解锁层级 + 已解锁团队 + 未解锁团队
   *        = 理论总算力（因为包含所有部分）
   *        = 总树数 * 22617
   */
  private async getContributionStats() {
    const [accounts, systemContributions, adoptionStats] = await Promise.all([
      this.prisma.syncedContributionAccount.aggregate({
        _sum: {
          totalContribution: true,
          effectiveContribution: true,
          personalContribution: true,
          teamLevelContribution: true,
          teamBonusContribution: true,
        },
        _count: true,
      }),
      this.prisma.syncedSystemContribution.aggregate({
        _sum: { contributionBalance: true },
        _count: true,
      }),
      this.prisma.syncedAdoption.aggregate({
        where: { status: 'MINING_ENABLED' },
        _sum: { treeCount: true },
        _count: true,
      }),
    ]);

    const totalTrees = adoptionStats._sum.treeCount || 0;

    // 有效算力 = 理论总算力 = 总树数 * 22617
    // 因为按照公式，有效算力包含所有部分（个人70%+运营12%+省1%+市2%+层级7.5%+团队7.5%=100%）
    const effectiveContribution = BASE_CONTRIBUTION_PER_TREE.mul(totalTrees);

    // 个人算力（已分配到用户账户）
    const personalContribution = new Decimal(accounts._sum.personalContribution || 0);

    // 系统账户算力（运营+省+市）
    const systemContribution = new Decimal(systemContributions._sum.contributionBalance || 0);

    return {
      totalAccounts: accounts._count,
      totalContribution: accounts._sum.totalContribution?.toString() || '0',
      effectiveContribution: effectiveContribution.toString(),
      personalContribution: personalContribution.toString(),
      teamLevelContribution:
        accounts._sum.teamLevelContribution?.toString() || '0',
      teamBonusContribution:
        accounts._sum.teamBonusContribution?.toString() || '0',
      systemAccounts: systemContributions._count,
      systemContribution: systemContribution.toString(),
      totalAdoptions: adoptionStats._count,
      totalTrees,
    };
  }

  /**
   * 获取详细算力分解统计（按用户需求）
   * 优先从 contribution-service API 获取完整数据（包含 pending），
   * 如果 API 调用失败则回退到本地数据
   */
  private async getDetailedContributionStats() {
    // 尝试从 contribution-service 获取完整数据
    const contributionServiceData = await this.fetchContributionServiceStats();
    if (contributionServiceData) {
      return contributionServiceData;
    }

    // 回退：从本地同步数据计算
    return this.getDetailedContributionStatsFromLocal();
  }

  /**
   * 从 contribution-service API 获取详细算力统计
   */
  private async fetchContributionServiceStats(): Promise<any | null> {
    const contributionServiceUrl = this.configService.get<string>(
      'CONTRIBUTION_SERVICE_URL',
      'http://localhost:3020',
    );

    try {
      const response = await fetch(`${contributionServiceUrl}/api/v2/contribution/stats`);
      if (!response.ok) {
        this.logger.warn(`Contribution service returned ${response.status}`);
        return null;
      }

      const result = await response.json();
      const data = result.data || result;

      // 获取系统账户实际值（本地数据）
      const systemAccounts = await this.prisma.syncedSystemContribution.findMany();
      let operationActual = new Decimal(0);
      let provinceActual = new Decimal(0);
      let cityActual = new Decimal(0);
      for (const account of systemAccounts) {
        const balance = new Decimal(account.contributionBalance || 0);
        if (account.accountType === 'OPERATION') operationActual = operationActual.plus(balance);
        else if (account.accountType === 'PROVINCE') provinceActual = provinceActual.plus(balance);
        else if (account.accountType === 'CITY') cityActual = cityActual.plus(balance);
      }

      return {
        totalTrees: data.totalTrees || 0,
        // 理论值
        networkTotalTheory: data.networkTotalContribution || '0',
        personalTheory: data.personalTotalContribution || '0',
        operationTheory: data.operationTotalContribution || '0',
        provinceTheory: data.provinceTotalContribution || '0',
        cityTheory: data.cityTotalContribution || '0',
        levelTheory: data.levelContribution?.total || '0',
        bonusTheory: data.bonusContribution?.total || '0',

        // 实际值
        operationActual: operationActual.toString(),
        provinceActual: provinceActual.toString(),
        cityActual: cityActual.toString(),

        // 层级算力详情（包含正确的 pending 数据）
        levelContribution: {
          total: data.levelContribution?.total || '0',
          unlocked: data.levelContribution?.unlocked || '0',
          pending: data.levelContribution?.pending || '0',
          byTier: {
            tier1: {
              unlocked: data.levelContribution?.byTier?.tier1?.unlocked || '0',
              pending: data.levelContribution?.byTier?.tier1?.pending || '0',
            },
            tier2: {
              unlocked: data.levelContribution?.byTier?.tier2?.unlocked || '0',
              pending: data.levelContribution?.byTier?.tier2?.pending || '0',
            },
            tier3: {
              unlocked: data.levelContribution?.byTier?.tier3?.unlocked || '0',
              pending: data.levelContribution?.byTier?.tier3?.pending || '0',
            },
          },
        },

        // 团队奖励算力详情（包含正确的 pending 数据）
        bonusContribution: {
          total: data.bonusContribution?.total || '0',
          unlocked: data.bonusContribution?.unlocked || '0',
          pending: data.bonusContribution?.pending || '0',
          byTier: {
            tier1: {
              unlocked: data.bonusContribution?.byTier?.tier1?.unlocked || '0',
              pending: data.bonusContribution?.byTier?.tier1?.pending || '0',
            },
            tier2: {
              unlocked: data.bonusContribution?.byTier?.tier2?.unlocked || '0',
              pending: data.bonusContribution?.byTier?.tier2?.pending || '0',
            },
            tier3: {
              unlocked: data.bonusContribution?.byTier?.tier3?.unlocked || '0',
              pending: data.bonusContribution?.byTier?.tier3?.pending || '0',
            },
          },
        },
      };
    } catch (error) {
      this.logger.warn(`Failed to fetch contribution service stats: ${error.message}`);
      return null;
    }
  }

  /**
   * 从本地同步数据计算详细算力统计（回退方案）
   */
  private async getDetailedContributionStatsFromLocal() {
    // 获取总树数
    const adoptionStats = await this.prisma.syncedAdoption.aggregate({
      where: { status: 'MINING_ENABLED' },
      _sum: { treeCount: true },
    });
    const totalTrees = adoptionStats._sum.treeCount || 0;

    // 按层级统计已分配的层级算力
    const levelRecords = await this.prisma.syncedContributionRecord.groupBy({
      by: ['levelDepth'],
      where: {
        sourceType: 'TEAM_LEVEL',
        levelDepth: { not: null },
      },
      _sum: { amount: true },
    });

    // 按档位统计已分配的团队奖励算力
    const bonusRecords = await this.prisma.syncedContributionRecord.groupBy({
      by: ['bonusTier'],
      where: {
        sourceType: 'TEAM_BONUS',
        bonusTier: { not: null },
      },
      _sum: { amount: true },
    });

    // 获取系统账户按类型的算力
    const systemAccounts = await this.prisma.syncedSystemContribution.findMany();

    // 汇总层级1-5, 6-10, 11-15
    let levelTier1 = new Decimal(0);
    let levelTier2 = new Decimal(0);
    let levelTier3 = new Decimal(0);
    for (const record of levelRecords) {
      const depth = record.levelDepth!;
      const amount = new Decimal(record._sum.amount || 0);
      if (depth >= 1 && depth <= 5) levelTier1 = levelTier1.plus(amount);
      else if (depth >= 6 && depth <= 10) levelTier2 = levelTier2.plus(amount);
      else if (depth >= 11 && depth <= 15) levelTier3 = levelTier3.plus(amount);
    }

    // 汇总团队奖励档位
    let bonusTier1 = new Decimal(0);
    let bonusTier2 = new Decimal(0);
    let bonusTier3 = new Decimal(0);
    for (const record of bonusRecords) {
      const tier = record.bonusTier!;
      const amount = new Decimal(record._sum.amount || 0);
      if (tier === 1) bonusTier1 = amount;
      else if (tier === 2) bonusTier2 = amount;
      else if (tier === 3) bonusTier3 = amount;
    }

    const levelUnlocked = levelTier1.plus(levelTier2).plus(levelTier3);
    const bonusUnlocked = bonusTier1.plus(bonusTier2).plus(bonusTier3);

    // 计算理论值
    const networkTotal = BASE_CONTRIBUTION_PER_TREE.mul(totalTrees);
    const personalTheory = networkTotal.mul(RATE_PERSONAL);
    const operationTheory = networkTotal.mul(RATE_OPERATION);
    const provinceTheory = networkTotal.mul(RATE_PROVINCE);
    const cityTheory = networkTotal.mul(RATE_CITY);
    const levelTheory = networkTotal.mul(RATE_LEVEL_TOTAL);
    const bonusTheory = networkTotal.mul(RATE_BONUS_TOTAL);

    // 计算未解锁（理论 - 已解锁）- 仅用于总数，各档位无法获取
    const levelPending = levelTheory.minus(levelUnlocked).greaterThan(0)
      ? levelTheory.minus(levelUnlocked)
      : new Decimal(0);
    const bonusPending = bonusTheory.minus(bonusUnlocked).greaterThan(0)
      ? bonusTheory.minus(bonusUnlocked)
      : new Decimal(0);

    // 系统账户按类型汇总
    let operationActual = new Decimal(0);
    let provinceActual = new Decimal(0);
    let cityActual = new Decimal(0);
    for (const account of systemAccounts) {
      const balance = new Decimal(account.contributionBalance || 0);
      if (account.accountType === 'OPERATION') operationActual = operationActual.plus(balance);
      else if (account.accountType === 'PROVINCE') provinceActual = provinceActual.plus(balance);
      else if (account.accountType === 'CITY') cityActual = cityActual.plus(balance);
    }

    return {
      totalTrees,
      // 理论值（基于总树数计算）
      networkTotalTheory: networkTotal.toString(),
      personalTheory: personalTheory.toString(),
      operationTheory: operationTheory.toString(),
      provinceTheory: provinceTheory.toString(),
      cityTheory: cityTheory.toString(),
      levelTheory: levelTheory.toString(),
      bonusTheory: bonusTheory.toString(),

      // 实际值（从数据库统计）
      operationActual: operationActual.toString(),
      provinceActual: provinceActual.toString(),
      cityActual: cityActual.toString(),

      // 层级算力详情（本地无法获取各档位 pending，显示为 N/A）
      levelContribution: {
        total: levelTheory.toString(),
        unlocked: levelUnlocked.toString(),
        pending: levelPending.toString(),
        byTier: {
          tier1: { unlocked: levelTier1.toString(), pending: 'N/A' },
          tier2: { unlocked: levelTier2.toString(), pending: 'N/A' },
          tier3: { unlocked: levelTier3.toString(), pending: 'N/A' },
        },
      },

      // 团队奖励算力详情（本地无法获取各档位 pending，显示为 N/A）
      bonusContribution: {
        total: bonusTheory.toString(),
        unlocked: bonusUnlocked.toString(),
        pending: bonusPending.toString(),
        byTier: {
          tier1: { unlocked: bonusTier1.toString(), pending: 'N/A' },
          tier2: { unlocked: bonusTier2.toString(), pending: 'N/A' },
          tier3: { unlocked: bonusTier3.toString(), pending: 'N/A' },
        },
      },
    };
  }

  /**
   * 获取挖矿统计
   */
  private async getMiningStats() {
    const [config, accounts, latestDailyStat] = await Promise.all([
      this.prisma.syncedMiningConfig.findFirst(),
      this.prisma.syncedMiningAccount.aggregate({
        _sum: {
          totalMined: true,
          availableBalance: true,
          frozenBalance: true,
        },
        _count: true,
      }),
      this.prisma.syncedDailyMiningStat.findFirst({
        orderBy: { statDate: 'desc' },
      }),
    ]);

    return {
      isActive: config?.isActive || false,
      currentEra: config?.currentEra || 0,
      totalShares: config?.totalShares?.toString() || '0',
      distributionPool: config?.distributionPool?.toString() || '0',
      remainingDistribution: config?.remainingDistribution?.toString() || '0',
      minuteDistribution: config?.minuteDistribution?.toString() || '0',
      activatedAt: config?.activatedAt,
      totalAccounts: accounts._count,
      totalMined: accounts._sum.totalMined?.toString() || '0',
      totalAvailable: accounts._sum.availableBalance?.toString() || '0',
      totalFrozen: accounts._sum.frozenBalance?.toString() || '0',
      latestDailyStat: latestDailyStat
        ? {
            date: latestDailyStat.statDate,
            totalDistributed: latestDailyStat.totalDistributed.toString(),
            totalBurned: latestDailyStat.totalBurned.toString(),
            participantCount: latestDailyStat.participantCount,
          }
        : null,
    };
  }

  /**
   * 获取交易统计
   */
  private async getTradingStats() {
    const [accounts, circulationPool, latestKLine] = await Promise.all([
      this.prisma.syncedTradingAccount.aggregate({
        _sum: {
          shareBalance: true,
          cashBalance: true,
          frozenShares: true,
          frozenCash: true,
          totalBought: true,
          totalSold: true,
        },
        _count: true,
      }),
      this.prisma.syncedCirculationPool.findFirst(),
      this.prisma.syncedDayKLine.findFirst({ orderBy: { klineDate: 'desc' } }),
    ]);

    return {
      totalAccounts: accounts._count,
      totalShareBalance: accounts._sum.shareBalance?.toString() || '0',
      totalCashBalance: accounts._sum.cashBalance?.toString() || '0',
      totalFrozenShares: accounts._sum.frozenShares?.toString() || '0',
      totalFrozenCash: accounts._sum.frozenCash?.toString() || '0',
      totalBought: accounts._sum.totalBought?.toString() || '0',
      totalSold: accounts._sum.totalSold?.toString() || '0',
      circulationPool: circulationPool
        ? {
            totalShares: circulationPool.totalShares.toString(),
            totalCash: circulationPool.totalCash.toString(),
          }
        : null,
      latestPrice: latestKLine?.close?.toString() || '1',
    };
  }

  /**
   * 获取每日报表
   */
  async getReports(
    page: number = 1,
    pageSize: number = 30,
  ): Promise<{ data: any[]; total: number; pagination: any }> {
    const [reports, total] = await Promise.all([
      this.prisma.dailyReport.findMany({
        orderBy: { reportDate: 'desc' },
        skip: (page - 1) * pageSize,
        take: pageSize,
      }),
      this.prisma.dailyReport.count(),
    ]);

    return {
      data: reports.map((r) => this.formatDailyReport(r)),
      total,
      pagination: {
        page,
        pageSize,
        total,
        totalPages: Math.ceil(total / pageSize),
      },
    };
  }

  /**
   * 获取审计日志
   */
  async getAuditLogs(options: {
    adminId?: string;
    action?: string;
    resource?: string;
    page?: number;
    pageSize?: number;
  }): Promise<{ data: any[]; total: number; pagination: any }> {
    const where: any = {};
    if (options.adminId) where.adminId = options.adminId;
    if (options.action) where.action = options.action;
    if (options.resource) where.resource = options.resource;

    const page = options.page ?? 1;
    const pageSize = options.pageSize ?? 50;

    const [logs, total] = await Promise.all([
      this.prisma.auditLog.findMany({
        where,
        include: { admin: { select: { username: true, name: true } } },
        orderBy: { createdAt: 'desc' },
        skip: (page - 1) * pageSize,
        take: pageSize,
      }),
      this.prisma.auditLog.count({ where }),
    ]);

    return {
      data: logs,
      total,
      pagination: {
        page,
        pageSize,
        total,
        totalPages: Math.ceil(total / pageSize),
      },
    };
  }

  // ===========================================================================
  // 远程服务数据获取（实时数据备选方案）
  // ===========================================================================

  /**
   * 从 mining-service 和 trading-service 获取实时数据
   * 用于补充 CDC 同步数据的不足
   */
  private async fetchRemoteServiceData(): Promise<RemoteServiceData> {
    // 检查缓存
    if (
      this.remoteDataCache &&
      Date.now() - this.remoteDataCache.fetchedAt.getTime() < this.CACHE_TTL_MS
    ) {
      return this.remoteDataCache;
    }

    const miningServiceUrl = this.configService.get<string>(
      'MINING_SERVICE_URL',
      'http://localhost:3021',
    );
    const tradingServiceUrl = this.configService.get<string>(
      'TRADING_SERVICE_URL',
      'http://localhost:3022',
    );

    let totalDistributed = '0';
    let totalBurned = '0';
    let circulationPool = '0';

    try {
      // 从 mining-service 获取已分配积分股
      const miningResponse = await fetch(
        `${miningServiceUrl}/api/v2/mining/admin/status`,
      );
      if (miningResponse.ok) {
        const miningResult = await miningResponse.json();
        const miningData = miningResult.data || miningResult;
        // 直接使用 totalDistributed（所有用户 totalMined 的总和）
        totalDistributed = miningData.totalDistributed || '0';
      }
    } catch (error) {
      this.logger.warn(`Failed to fetch mining service data: ${error.message}`);
    }

    try {
      // 从 trading-service 获取市场概览（包含销毁和流通池数据）
      const marketResponse = await fetch(
        `${tradingServiceUrl}/api/v2/asset/market`,
      );
      if (marketResponse.ok) {
        const marketResult = await marketResponse.json();
        const marketData = marketResult.data || marketResult;
        // blackHoleAmount 是已销毁总量
        totalBurned = marketData.blackHoleAmount || '0';
        // circulationPool 是流通池余额
        circulationPool = marketData.circulationPool || '0';
      }
    } catch (error) {
      this.logger.warn(`Failed to fetch market overview: ${error.message}`);
    }

    // 更新缓存
    this.remoteDataCache = {
      totalDistributed,
      totalBurned,
      circulationPool,
      fetchedAt: new Date(),
    };

    return this.remoteDataCache;
  }

  // ===========================================================================
  // 辅助方法
  // ===========================================================================

  private formatDailyReport(report: any) {
    return {
      id: report.id,
      reportDate: report.reportDate,
      users: {
        total: report.totalUsers,
        new: report.newUsers,
        active: report.activeUsers,
      },
      adoptions: {
        total: report.totalAdoptions,
        new: report.newAdoptions,
        totalTrees: report.totalTrees,
      },
      contribution: {
        total: report.totalContribution?.toString() || '0',
        growth: report.contributionGrowth?.toString() || '0',
      },
      mining: {
        distributed: report.totalDistributed?.toString() || '0',
        burned: report.totalBurned?.toString() || '0',
      },
      trading: {
        volume: report.tradingVolume?.toString() || '0',
        amount: report.tradingAmount?.toString() || '0',
        count: report.tradeCount,
      },
      price: {
        open: report.openPrice?.toString() || '1',
        close: report.closePrice?.toString() || '1',
        high: report.highPrice?.toString() || '1',
        low: report.lowPrice?.toString() || '1',
      },
      createdAt: report.createdAt,
    };
  }
}
