import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CoManagedWalletRepository } from '../../../domain/repositories/co-managed-wallet.repository';
import { CoManagedWalletEntity } from '../../../domain/entities/co-managed-wallet.entity';
import { CoManagedWalletMapper } from '../mappers/co-managed-wallet.mapper';

@Injectable()
export class CoManagedWalletRepositoryImpl implements CoManagedWalletRepository {
  constructor(
    private readonly prisma: PrismaService,
    private readonly mapper: CoManagedWalletMapper,
  ) {}

  async save(entity: CoManagedWalletEntity): Promise<CoManagedWalletEntity> {
    const data = this.mapper.walletToPersistence(entity);

    const saved = await this.prisma.coManagedWallet.upsert({
      where: { id: entity.id },
      create: {
        ...data,
        createdAt: entity.createdAt,
      },
      update: data,
    });

    return this.mapper.walletToDomain(saved);
  }

  async findById(id: string): Promise<CoManagedWalletEntity | null> {
    const wallet = await this.prisma.coManagedWallet.findUnique({
      where: { id },
    });

    if (!wallet) {
      return null;
    }

    return this.mapper.walletToDomain(wallet);
  }

  async findBySessionId(sessionId: string): Promise<CoManagedWalletEntity | null> {
    const wallet = await this.prisma.coManagedWallet.findUnique({
      where: { sessionId },
    });

    if (!wallet) {
      return null;
    }

    return this.mapper.walletToDomain(wallet);
  }

  async findByCreatedBy(createdBy: string): Promise<CoManagedWalletEntity[]> {
    const wallets = await this.prisma.coManagedWallet.findMany({
      where: { createdBy },
      orderBy: { createdAt: 'desc' },
    });

    return wallets.map((w) => this.mapper.walletToDomain(w));
  }

  async findAll(params: {
    page: number;
    pageSize: number;
  }): Promise<{
    items: CoManagedWalletEntity[];
    total: number;
  }> {
    const [wallets, total] = await Promise.all([
      this.prisma.coManagedWallet.findMany({
        skip: (params.page - 1) * params.pageSize,
        take: params.pageSize,
        orderBy: { createdAt: 'desc' },
      }),
      this.prisma.coManagedWallet.count(),
    ]);

    return {
      items: wallets.map((w) => this.mapper.walletToDomain(w)),
      total,
    };
  }

  async delete(id: string): Promise<void> {
    await this.prisma.coManagedWallet.delete({
      where: { id },
    });
  }
}
