import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';
import {
  IAdoptionInjectionRecordRepository,
  AdoptionInjectionRecordDto,
} from '@/domain/repositories/adoption-injection-record.repository.interface';

@Injectable()
export class AdoptionInjectionRecordRepositoryImpl implements IAdoptionInjectionRecordRepository {
  constructor(private readonly prisma: PrismaService) {}

  async save(record: AdoptionInjectionRecordDto): Promise<AdoptionInjectionRecordDto> {
    const data = {
      adoptionId: record.adoptionId,
      accountSequence: record.accountSequence,
      treeCount: record.treeCount,
      adoptionDate: record.adoptionDate,
      fromAddress: record.fromAddress,
      toAddress: record.toAddress,
      amount: new Prisma.Decimal(record.amount),
      chainType: record.chainType,
      txHash: record.txHash,
      blockNumber: record.blockNumber,
      gasUsed: record.gasUsed,
      memo: record.memo,
      status: record.status,
      errorMessage: record.errorMessage,
    };

    if (record.id) {
      const updated = await this.prisma.adoptionInjectionRecord.update({
        where: { id: record.id },
        data,
      });
      return this.mapToDto(updated);
    } else {
      const created = await this.prisma.adoptionInjectionRecord.create({
        data,
      });
      return this.mapToDto(created);
    }
  }

  async findByAdoptionId(adoptionId: string): Promise<AdoptionInjectionRecordDto | null> {
    const record = await this.prisma.adoptionInjectionRecord.findFirst({
      where: { adoptionId },
    });
    return record ? this.mapToDto(record) : null;
  }

  async findByAccountSequence(accountSequence: string): Promise<AdoptionInjectionRecordDto[]> {
    const records = await this.prisma.adoptionInjectionRecord.findMany({
      where: { accountSequence },
      orderBy: { createdAt: 'desc' },
    });
    return records.map(this.mapToDto);
  }

  async markConfirmed(id: bigint, txHash: string, blockNumber: bigint, gasUsed: string): Promise<void> {
    await this.prisma.adoptionInjectionRecord.update({
      where: { id },
      data: {
        txHash,
        blockNumber,
        gasUsed,
        status: 'CONFIRMED',
      },
    });
  }

  async markFailed(id: bigint, errorMessage: string): Promise<void> {
    await this.prisma.adoptionInjectionRecord.update({
      where: { id },
      data: {
        errorMessage,
        status: 'FAILED',
      },
    });
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private mapToDto(record: any): AdoptionInjectionRecordDto {
    return {
      id: record.id,
      adoptionId: record.adoptionId,
      accountSequence: record.accountSequence,
      treeCount: record.treeCount,
      adoptionDate: record.adoptionDate,
      fromAddress: record.fromAddress,
      toAddress: record.toAddress,
      amount: record.amount.toString(),
      chainType: record.chainType,
      txHash: record.txHash,
      blockNumber: record.blockNumber,
      gasUsed: record.gasUsed,
      memo: record.memo,
      status: record.status,
      errorMessage: record.errorMessage,
      createdAt: record.createdAt,
      updatedAt: record.updatedAt,
    };
  }
}
