import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { RewardSummaryMapper } from '../mappers/reward-summary.mapper';
import { RewardSummary } from '../../../domain/aggregates/reward-summary/reward-summary.aggregate';
import { IRewardSummaryRepository } from '../../../domain/repositories/reward-summary.repository.interface';

@Injectable()
export class RewardSummaryRepositoryImpl implements IRewardSummaryRepository {
  constructor(private readonly prisma: PrismaService) {}

  async save(summary: RewardSummary): Promise<void> {
    const data = RewardSummaryMapper.toPersistence(summary);

    if (summary.id) {
      await this.prisma.rewardSummary.update({
        where: { id: summary.id },
        data: {
          pendingUsdt: data.pendingUsdt,
          pendingHashpower: data.pendingHashpower,
          pendingExpireAt: data.pendingExpireAt,
          settleableUsdt: data.settleableUsdt,
          settleableHashpower: data.settleableHashpower,
          settledTotalUsdt: data.settledTotalUsdt,
          settledTotalHashpower: data.settledTotalHashpower,
          expiredTotalUsdt: data.expiredTotalUsdt,
          expiredTotalHashpower: data.expiredTotalHashpower,
        },
      });
    } else {
      const created = await this.prisma.rewardSummary.create({
        data: {
          userId: data.userId,
          accountSequence: data.accountSequence,
          pendingUsdt: data.pendingUsdt,
          pendingHashpower: data.pendingHashpower,
          pendingExpireAt: data.pendingExpireAt,
          settleableUsdt: data.settleableUsdt,
          settleableHashpower: data.settleableHashpower,
          settledTotalUsdt: data.settledTotalUsdt,
          settledTotalHashpower: data.settledTotalHashpower,
          expiredTotalUsdt: data.expiredTotalUsdt,
          expiredTotalHashpower: data.expiredTotalHashpower,
        },
      });
      summary.setId(created.id);
    }
  }

  async findByUserId(userId: bigint): Promise<RewardSummary | null> {
    const raw = await this.prisma.rewardSummary.findUnique({
      where: { userId },
    });
    return raw ? RewardSummaryMapper.toDomain(raw) : null;
  }

  async getOrCreate(userId: bigint, accountSequence: string): Promise<RewardSummary> {
    const existing = await this.findByUserId(userId);
    if (existing) {
      return existing;
    }

    const newSummary = RewardSummary.create(userId, accountSequence);
    await this.save(newSummary);
    return newSummary;
  }

  async findByUserIds(userIds: bigint[]): Promise<Map<string, RewardSummary>> {
    const rawList = await this.prisma.rewardSummary.findMany({
      where: {
        userId: { in: userIds },
      },
    });

    const result = new Map<string, RewardSummary>();
    for (const raw of rawList) {
      result.set(raw.userId.toString(), RewardSummaryMapper.toDomain(raw));
    }
    return result;
  }

  async findTopSettleableUsers(limit: number): Promise<RewardSummary[]> {
    const rawList = await this.prisma.rewardSummary.findMany({
      where: {
        settleableUsdt: { gt: 0 },
      },
      orderBy: { settleableUsdt: 'desc' },
      take: limit,
    });

    return rawList.map(RewardSummaryMapper.toDomain);
  }

  async findByAccountSequence(accountSequence: string): Promise<RewardSummary | null> {
    const raw = await this.prisma.rewardSummary.findUnique({
      where: { accountSequence },
    });
    return raw ? RewardSummaryMapper.toDomain(raw) : null;
  }

  async getOrCreateByAccountSequence(accountSequence: string): Promise<RewardSummary> {
    const existing = await this.findByAccountSequence(accountSequence);
    if (existing) {
      return existing;
    }

    // Need to find userId by accountSequence - this requires user service integration
    // For now, we'll throw an error indicating this needs to be implemented
    throw new Error('getOrCreateByAccountSequence requires userId mapping - use getOrCreate with userId instead');
  }
}
