import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { IMarketMakerCheckpointRepository } from '@/domain/repositories/market-maker-deposit.repository.interface';
import { ChainType, BlockNumber } from '@/domain/value-objects';
import { MarketMakerAssetType } from '@/domain/enums';

@Injectable()
export class MarketMakerCheckpointRepositoryImpl implements IMarketMakerCheckpointRepository {
  constructor(private readonly prisma: PrismaService) {}

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

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

  async initializeIfNotExists(
    chainType: ChainType,
    assetType: MarketMakerAssetType,
    blockNumber: BlockNumber,
  ): Promise<void> {
    const existing = await this.prisma.marketMakerBlockCheckpoint.findUnique({
      where: {
        uk_mm_chain_asset: {
          chainType: chainType.toString(),
          assetType,
        },
      },
    });

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

  async recordError(
    chainType: ChainType,
    assetType: MarketMakerAssetType,
    error: string,
  ): Promise<void> {
    await this.prisma.marketMakerBlockCheckpoint.upsert({
      where: {
        uk_mm_chain_asset: {
          chainType: chainType.toString(),
          assetType,
        },
      },
      update: {
        isHealthy: false,
        lastError: error,
      },
      create: {
        chainType: chainType.toString(),
        assetType,
        lastScannedBlock: BigInt(0),
        lastScannedAt: new Date(),
        isHealthy: false,
        lastError: error,
      },
    });
  }

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