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

@Injectable()
export class DashboardService {
  private readonly logger = new Logger(DashboardService.name);

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

  /**
   * 获取仪表盘统计数据
   * 优先从本地同步表获取，如果没有数据则调用远程服务
   */
  async getDashboardStats(): Promise<any> {
    const [
      userStats,
      contributionStats,
      miningStats,
      tradingStats,
      latestReport,
      latestKLine,
    ] = 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' } }),
    ]);

    return {
      users: userStats,
      contribution: contributionStats,
      mining: miningStats,
      trading: tradingStats,
      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,
    };
  }

  /**
   * 获取算力统计
   */
  private async getContributionStats() {
    const accounts = await this.prisma.syncedContributionAccount.aggregate({
      _sum: {
        totalContribution: true,
        effectiveContribution: true,
        personalContribution: true,
        teamLevelContribution: true,
        teamBonusContribution: true,
      },
      _count: true,
    });

    const systemContributions =
      await this.prisma.syncedSystemContribution.aggregate({
        _sum: { contributionBalance: true },
        _count: true,
      });

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

  /**
   * 获取挖矿统计
   */
  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),
      },
    };
  }

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

  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,
    };
  }
}
