import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import {
  IBlockCheckpointRepository,
  BlockCheckpointData,
} from '@/domain/repositories/block-checkpoint.repository.interface';
import { ChainType, BlockNumber } from '@/domain/value-objects';

@Injectable()
export class BlockCheckpointRepositoryImpl implements IBlockCheckpointRepository {
  constructor(private readonly prisma: PrismaService) {}

  async getLastScannedBlock(chainType: ChainType): Promise<BlockNumber | null> {
    const record = await this.prisma.blockCheckpoint.findUnique({
      where: { chainType: chainType.toString() },
    });
    return record ? BlockNumber.create(record.lastScannedBlock) : null;
  }

  async updateCheckpoint(chainType: ChainType, blockNumber: BlockNumber): Promise<void> {
    await this.prisma.blockCheckpoint.upsert({
      where: { chainType: chainType.toString() },
      update: {
        lastScannedBlock: blockNumber.value,
        lastScannedAt: new Date(),
        isHealthy: true,
        lastError: null,
      },
      create: {
        chainType: chainType.toString(),
        lastScannedBlock: blockNumber.value,
        lastScannedAt: new Date(),
        isHealthy: true,
      },
    });
  }

  async recordError(chainType: ChainType, error: string): Promise<void> {
    await this.prisma.blockCheckpoint.update({
      where: { chainType: chainType.toString() },
      data: {
        isHealthy: false,
        lastError: error,
      },
    });
  }

  async markHealthy(chainType: ChainType): Promise<void> {
    await this.prisma.blockCheckpoint.update({
      where: { chainType: chainType.toString() },
      data: {
        isHealthy: true,
        lastError: null,
      },
    });
  }

  async getCheckpoint(chainType: ChainType): Promise<BlockCheckpointData | null> {
    const record = await this.prisma.blockCheckpoint.findUnique({
      where: { chainType: chainType.toString() },
    });

    if (!record) return null;

    return {
      chainType: record.chainType,
      lastScannedBlock: record.lastScannedBlock,
      lastScannedAt: record.lastScannedAt,
      isHealthy: record.isHealthy,
      lastError: record.lastError ?? undefined,
    };
  }

  async initializeIfNotExists(chainType: ChainType, startBlock: BlockNumber): Promise<void> {
    const existing = await this.prisma.blockCheckpoint.findUnique({
      where: { chainType: chainType.toString() },
    });

    if (!existing) {
      await this.prisma.blockCheckpoint.create({
        data: {
          chainType: chainType.toString(),
          lastScannedBlock: startBlock.value,
          lastScannedAt: new Date(),
          isHealthy: true,
        },
      });
    }
  }
}
