import { Injectable } from '@nestjs/common';
import {
  CoManagedWalletSession as PrismaSession,
  CoManagedWallet as PrismaWallet,
  WalletSessionStatus as PrismaWalletSessionStatus,
} from '@prisma/client';
import {
  CoManagedWalletSessionEntity,
  CoManagedWalletEntity,
  Participant,
  ThresholdConfig,
} from '../../../domain/entities/co-managed-wallet.entity';
import {
  WalletSessionStatus,
  ParticipantStatus,
} from '../../../domain/enums/wallet-session-status.enum';

/**
 * Prisma 会话模型类型 - 使用 Prisma 生成的类型
 */
export type PrismaCoManagedWalletSession = PrismaSession;

/**
 * Prisma 钱包模型类型 - 使用 Prisma 生成的类型
 */
export type PrismaCoManagedWallet = PrismaWallet;

@Injectable()
export class CoManagedWalletMapper {
  /**
   * 将 Prisma 会话模型转换为领域实体
   */
  sessionToDomain(prisma: PrismaCoManagedWalletSession): CoManagedWalletSessionEntity {
    const participants: Participant[] = JSON.parse(prisma.participants).map(
      (p: { partyId: string; name: string; status: string; joinedAt: string }) => ({
        partyId: p.partyId,
        name: p.name,
        status: p.status as ParticipantStatus,
        joinedAt: new Date(p.joinedAt),
      }),
    );

    const threshold: ThresholdConfig = {
      t: prisma.thresholdT,
      n: prisma.thresholdN,
    };

    return CoManagedWalletSessionEntity.reconstitute({
      id: prisma.id,
      walletName: prisma.walletName,
      threshold,
      inviteCode: prisma.inviteCode,
      status: prisma.status as WalletSessionStatus,
      participants,
      currentRound: prisma.currentRound,
      totalRounds: prisma.totalRounds,
      publicKey: prisma.publicKey,
      error: prisma.error,
      createdAt: prisma.createdAt,
      updatedAt: prisma.updatedAt,
      createdBy: prisma.createdBy,
    });
  }

  /**
   * 将领域实体转换为 Prisma 持久化格式
   */
  sessionToPersistence(
    domain: CoManagedWalletSessionEntity,
  ): Omit<PrismaCoManagedWalletSession, 'createdAt' | 'updatedAt'> {
    return {
      id: domain.id,
      walletName: domain.walletName,
      thresholdT: domain.threshold.t,
      thresholdN: domain.threshold.n,
      inviteCode: domain.inviteCode,
      status: domain.status as PrismaWalletSessionStatus,
      participants: JSON.stringify(
        domain.participants.map((p) => ({
          partyId: p.partyId,
          name: p.name,
          status: p.status,
          joinedAt: p.joinedAt.toISOString(),
        })),
      ),
      currentRound: domain.currentRound,
      totalRounds: domain.totalRounds,
      publicKey: domain.publicKey,
      error: domain.error,
      createdBy: domain.createdBy,
    };
  }

  /**
   * 将 Prisma 钱包模型转换为领域实体
   */
  walletToDomain(prisma: PrismaCoManagedWallet): CoManagedWalletEntity {
    const participants: Array<{ partyId: string; name: string }> = JSON.parse(
      prisma.participants,
    );

    const threshold: ThresholdConfig = {
      t: prisma.thresholdT,
      n: prisma.thresholdN,
    };

    return CoManagedWalletEntity.reconstitute({
      id: prisma.id,
      sessionId: prisma.sessionId,
      name: prisma.name,
      publicKey: prisma.publicKey,
      threshold,
      participants,
      createdAt: prisma.createdAt,
      createdBy: prisma.createdBy,
    });
  }

  /**
   * 将领域实体转换为 Prisma 持久化格式
   */
  walletToPersistence(
    domain: CoManagedWalletEntity,
  ): Omit<PrismaCoManagedWallet, 'createdAt'> {
    return {
      id: domain.id,
      sessionId: domain.sessionId,
      name: domain.name,
      publicKey: domain.publicKey,
      thresholdT: domain.threshold.t,
      thresholdN: domain.threshold.n,
      participants: JSON.stringify(domain.participants),
      createdBy: domain.createdBy,
    };
  }
}
