import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import {
  SmsVerificationRepository,
  SmsVerificationData,
  SmsVerificationType,
  Phone,
} from '@/domain';

@Injectable()
export class PrismaSmsVerificationRepository implements SmsVerificationRepository {
  constructor(private readonly prisma: PrismaService) {}

  async create(data: {
    phone: Phone;
    code: string;
    type: SmsVerificationType;
    expiresAt: Date;
  }): Promise<SmsVerificationData> {
    const created = await this.prisma.smsVerification.create({
      data: {
        phone: data.phone.value,
        code: data.code,
        type: data.type,
        expiresAt: data.expiresAt,
      },
    });

    return this.toDomain(created);
  }

  async findLatestValid(phone: Phone, type: SmsVerificationType): Promise<SmsVerificationData | null> {
    const data = await this.prisma.smsVerification.findFirst({
      where: {
        phone: phone.value,
        type,
        expiresAt: { gt: new Date() },
        verifiedAt: null,
      },
      orderBy: { createdAt: 'desc' },
    });

    if (!data) return null;
    return this.toDomain(data);
  }

  async incrementAttempts(id: bigint): Promise<void> {
    await this.prisma.smsVerification.update({
      where: { id },
      data: { attempts: { increment: 1 } },
    });
  }

  async markAsVerified(id: bigint): Promise<void> {
    await this.prisma.smsVerification.update({
      where: { id },
      data: { verifiedAt: new Date() },
    });
  }

  async getDailySendCount(phone: Phone): Promise<number> {
    const today = new Date();
    today.setHours(0, 0, 0, 0);

    return this.prisma.smsVerification.count({
      where: {
        phone: phone.value,
        createdAt: { gte: today },
      },
    });
  }

  async deleteExpired(): Promise<number> {
    const result = await this.prisma.smsVerification.deleteMany({
      where: {
        expiresAt: { lt: new Date() },
      },
    });

    return result.count;
  }

  private toDomain(data: any): SmsVerificationData {
    return {
      id: data.id,
      phone: Phone.create(data.phone),
      code: data.code,
      type: data.type as SmsVerificationType,
      expiresAt: data.expiresAt,
      verifiedAt: data.verifiedAt,
      attempts: data.attempts,
      createdAt: data.createdAt,
    };
  }
}
