import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { RedisService } from '../../infrastructure/redis/redis.service';
import { ContributionWalletService } from '../services/contribution-wallet.service';
import { UserWalletType, AssetType } from '@prisma/client';
import Decimal from 'decimal.js';

@Injectable()
export class ContributionExpiryScheduler {
  private readonly logger = new Logger(ContributionExpiryScheduler.name);
  private readonly LOCK_KEY = 'mining-wallet:contribution-expiry:lock';
  private readonly LOCK_TTL = 3600; // 1 hour

  constructor(
    private readonly prisma: PrismaService,
    private readonly redis: RedisService,
    private readonly contributionWalletService: ContributionWalletService,
  ) {}

  /**
   * 每日凌晨1点执行过期检查
   */
  @Cron('0 1 * * *')
  async processExpiredContributions(): Promise<void> {
    const lockValue = await this.redis.acquireLock(this.LOCK_KEY, this.LOCK_TTL);
    if (!lockValue) {
      this.logger.debug('Another instance is processing expired contributions');
      return;
    }

    try {
      this.logger.log('Starting contribution expiry processing');

      const today = new Date();
      today.setHours(0, 0, 0, 0);

      // 查找所有过期的贡献值交易记录
      // 通过 metadata.expireDate 字段判断
      const expiredTransactions = await this.prisma.userWalletTransaction.findMany({
        where: {
          walletType: UserWalletType.CONTRIBUTION,
          assetType: AssetType.CONTRIBUTION,
          amount: { gt: 0 }, // 只查找入账记录
          // 检查 metadata 中的 expireDate
          // 注意: Prisma 的 JSON 过滤有限制，可能需要原生查询
        },
        take: 1000, // 每次处理1000条
        orderBy: { createdAt: 'asc' },
      });

      let expiredCount = 0;

      for (const tx of expiredTransactions) {
        const metadata = tx.metadata as any;
        if (!metadata?.expireDate || metadata?.isExpired) {
          continue;
        }

        const expireDate = new Date(metadata.expireDate);
        if (expireDate > today) {
          continue;
        }

        try {
          await this.contributionWalletService.expireContribution(
            tx.id,
            tx.accountSequence,
            new Decimal(tx.amount.toString()),
          );

          // 标记原交易为已过期
          await this.prisma.userWalletTransaction.update({
            where: { id: tx.id },
            data: {
              metadata: {
                ...metadata,
                isExpired: true,
                expiredAt: new Date().toISOString(),
              },
            },
          });

          expiredCount++;
        } catch (error) {
          this.logger.error(
            `Failed to expire contribution ${tx.id}`,
            error instanceof Error ? error.stack : error,
          );
        }
      }

      this.logger.log(`Processed ${expiredCount} expired contributions`);
    } finally {
      await this.redis.releaseLock(this.LOCK_KEY, lockValue);
    }
  }

  /**
   * 每天凌晨3点清理过期的 ProcessedEvent 记录（保留24小时）
   */
  @Cron('0 3 * * *')
  async cleanupProcessedEvents(): Promise<void> {
    const lockValue = await this.redis.acquireLock(
      `${this.LOCK_KEY}:cleanup`,
      60,
    );
    if (!lockValue) {
      return;
    }

    try {
      const cutoffDate = new Date();
      cutoffDate.setHours(cutoffDate.getHours() - 24);

      const result = await this.prisma.processedEvent.deleteMany({
        where: {
          processedAt: { lt: cutoffDate },
        },
      });

      if (result.count > 0) {
        this.logger.log(
          `Cleaned up ${result.count} processed events older than 24 hours`,
        );
      }
    } finally {
      await this.redis.releaseLock(`${this.LOCK_KEY}:cleanup`, lockValue);
    }
  }
}
