import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import {
  MpcKeyShareRepository,
  MpcKeyShareData,
  MpcKeyShare,
} from '@/domain/repositories/mpc-key-share.repository.interface';
import { UserId } from '@/domain/value-objects';

@Injectable()
export class MpcKeyShareRepositoryImpl implements MpcKeyShareRepository {
  constructor(private readonly prisma: PrismaService) {}

  async saveServerShare(data: MpcKeyShareData): Promise<MpcKeyShare> {
    const result = await this.prisma.mpcKeyShare.create({
      data: {
        userId: data.userId,
        publicKey: data.publicKey,
        partyIndex: data.partyIndex,
        threshold: data.threshold,
        totalParties: data.totalParties,
        encryptedShareData: data.encryptedShareData,
        status: 'ACTIVE',
      },
    });

    return this.toDomain(result);
  }

  async findByUserId(userId: UserId): Promise<MpcKeyShare | null> {
    const result = await this.prisma.mpcKeyShare.findUnique({
      where: { userId: BigInt(userId.value) },
    });
    return result ? this.toDomain(result) : null;
  }

  async findByPublicKey(publicKey: string): Promise<MpcKeyShare | null> {
    const result = await this.prisma.mpcKeyShare.findUnique({
      where: { publicKey },
    });
    return result ? this.toDomain(result) : null;
  }

  async updateStatus(shareId: bigint, status: string): Promise<void> {
    await this.prisma.mpcKeyShare.update({
      where: { shareId },
      data: { status },
    });
  }

  async rotateShare(shareId: bigint, newEncryptedData: string): Promise<void> {
    await this.prisma.mpcKeyShare.update({
      where: { shareId },
      data: {
        encryptedShareData: newEncryptedData,
        rotatedAt: new Date(),
      },
    });
  }

  private toDomain(data: any): MpcKeyShare {
    return {
      shareId: data.shareId,
      userId: data.userId,
      publicKey: data.publicKey,
      partyIndex: data.partyIndex,
      threshold: data.threshold,
      totalParties: data.totalParties,
      encryptedShareData: data.encryptedShareData,
      status: data.status,
      createdAt: data.createdAt,
      rotatedAt: data.rotatedAt,
    };
  }
}
