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

interface MiningServiceSystemAccount {
  accountType: string;
  name: string;
  totalMined: string;
  availableBalance: string;
  totalContribution: string;
  lastSyncedAt: string | null;
}

interface MiningServiceResponse {
  accounts: MiningServiceSystemAccount[];
  total: number;
}

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

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

  /**
   * 从 mining-service 获取系统账户挖矿数据
   */
  private async fetchMiningServiceSystemAccounts(): Promise<Map<string, MiningServiceSystemAccount>> {
    const miningServiceUrl = this.configService.get<string>(
      'MINING_SERVICE_URL',
      'http://localhost:3021',
    );

    try {
      const response = await firstValueFrom(
        this.httpService.get<MiningServiceResponse>(
          `${miningServiceUrl}/admin/system-accounts`,
        ),
      );

      const miningDataMap = new Map<string, MiningServiceSystemAccount>();
      for (const account of response.data.accounts) {
        miningDataMap.set(account.accountType, account);
      }

      return miningDataMap;
    } catch (error) {
      this.logger.warn(
        `Failed to fetch mining service system accounts: ${error.message}`,
      );
      return new Map();
    }
  }

  /**
   * 获取系统账户列表
   * 从 CDC 同步的钱包系统账户表读取数据，并合并挖矿数据
   */
  async getSystemAccounts() {
    // 从 CDC 同步的 SyncedWalletSystemAccount 表获取数据
    const syncedAccounts = await this.prisma.syncedWalletSystemAccount.findMany({
      orderBy: { accountType: 'asc' },
    });

    // 从 CDC 同步的 SyncedSystemContribution 获取算力数据
    const syncedContributions =
      await this.prisma.syncedSystemContribution.findMany();

    // 从 mining-service 获取挖矿数据
    const miningDataMap = await this.fetchMiningServiceSystemAccounts();

    // 构建算力数据映射
    const contributionMap = new Map<string, any>();
    for (const contrib of syncedContributions) {
      contributionMap.set(contrib.accountType, contrib);
    }

    // 构建返回数据
    const accounts = syncedAccounts.map((account) => {
      const contrib = contributionMap.get(account.accountType);
      const miningData = miningDataMap.get(account.accountType);

      return {
        id: account.originalId,
        accountType: account.accountType,
        name: account.name,
        code: account.code,
        provinceId: account.provinceId,
        cityId: account.cityId,
        shareBalance: account.shareBalance.toString(),
        usdtBalance: account.usdtBalance.toString(),
        greenPointBalance: account.greenPointBalance.toString(),
        frozenShare: account.frozenShare.toString(),
        frozenUsdt: account.frozenUsdt.toString(),
        totalInflow: account.totalInflow.toString(),
        totalOutflow: account.totalOutflow.toString(),
        blockchainAddress: account.blockchainAddress,
        isActive: account.isActive,
        contributionBalance: contrib?.contributionBalance?.toString() || '0',
        contributionNeverExpires: contrib?.contributionNeverExpires || false,
        // 挖矿数据
        totalMined: miningData?.totalMined || '0',
        availableBalance: miningData?.availableBalance || '0',
        miningContribution: miningData?.totalContribution || '0',
        miningLastSyncedAt: miningData?.lastSyncedAt || null,
        syncedAt: account.syncedAt,
        source: 'cdc',
      };
    });

    return {
      accounts,
      total: accounts.length,
    };
  }

  /**
   * 获取系统账户汇总
   */
  async getSystemAccountsSummary() {
    const [
      syncedSystemAccounts,
      syncedPoolAccounts,
      syncedContributions,
      miningConfig,
      circulationPool,
    ] = await Promise.all([
      this.prisma.syncedWalletSystemAccount.findMany(),
      this.prisma.syncedWalletPoolAccount.findMany(),
      this.prisma.syncedSystemContribution.findMany(),
      this.prisma.syncedMiningConfig.findFirst(),
      this.prisma.syncedCirculationPool.findFirst(),
    ]);

    // 从 mining-service 获取挖矿数据汇总
    const miningDataMap = await this.fetchMiningServiceSystemAccounts();

    // 计算总挖矿积分股
    let totalMined = 0;
    for (const miningData of miningDataMap.values()) {
      totalMined += Number(miningData.totalMined || 0);
    }

    // 计算总算力
    let totalSyncedContribution = 0n;
    for (const contrib of syncedContributions) {
      totalSyncedContribution += BigInt(
        contrib.contributionBalance.toString().replace('.', ''),
      );
    }

    return {
      systemAccounts: {
        count: syncedSystemAccounts.length,
        totalBalance: syncedSystemAccounts.reduce(
          (sum, acc) => sum + Number(acc.shareBalance),
          0,
        ).toFixed(8),
        totalMined: totalMined.toFixed(8),
      },
      poolAccounts: {
        count: syncedPoolAccounts.length,
        pools: syncedPoolAccounts.map((pool) => ({
          poolType: pool.poolType,
          name: pool.name,
          balance: pool.balance.toString(),
          targetBurn: pool.targetBurn?.toString(),
          remainingBurn: pool.remainingBurn?.toString(),
        })),
      },
      syncedContributions: {
        count: syncedContributions.length,
        totalBalance: (Number(totalSyncedContribution) / 100000000).toFixed(8),
      },
      miningConfig: miningConfig
        ? {
            totalShares: miningConfig.totalShares.toString(),
            distributionPool: miningConfig.distributionPool.toString(),
            remainingDistribution: miningConfig.remainingDistribution.toString(),
            currentEra: miningConfig.currentEra,
            isActive: miningConfig.isActive,
            activatedAt: miningConfig.activatedAt,
          }
        : null,
      circulationPool: circulationPool
        ? {
            totalShares: circulationPool.totalShares.toString(),
            totalCash: circulationPool.totalCash.toString(),
          }
        : null,
    };
  }

  /**
   * 获取系统账户挖矿记录
   */
  async getSystemAccountMiningRecords(
    accountType: string,
    page: number = 1,
    pageSize: number = 20,
  ) {
    const miningServiceUrl = this.configService.get<string>(
      'MINING_SERVICE_URL',
      'http://localhost:3021',
    );

    try {
      const response = await firstValueFrom(
        this.httpService.get(
          `${miningServiceUrl}/admin/system-accounts/${accountType}/records`,
          {
            params: { page, pageSize },
          },
        ),
      );

      return response.data;
    } catch (error) {
      this.logger.warn(
        `Failed to fetch system account mining records: ${error.message}`,
      );
      return { records: [], total: 0, page, pageSize };
    }
  }

  /**
   * 获取系统账户交易记录
   */
  async getSystemAccountTransactions(
    accountType: string,
    page: number = 1,
    pageSize: number = 20,
  ) {
    const miningServiceUrl = this.configService.get<string>(
      'MINING_SERVICE_URL',
      'http://localhost:3021',
    );

    try {
      const response = await firstValueFrom(
        this.httpService.get(
          `${miningServiceUrl}/admin/system-accounts/${accountType}/transactions`,
          {
            params: { page, pageSize },
          },
        ),
      );

      return response.data;
    } catch (error) {
      this.logger.warn(
        `Failed to fetch system account transactions: ${error.message}`,
      );
      return { transactions: [], total: 0, page, pageSize };
    }
  }
}
