import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { RefreshTokenRepository, RefreshTokenData } from '@/domain';

@Injectable()
export class PrismaRefreshTokenRepository implements RefreshTokenRepository {
  constructor(private readonly prisma: PrismaService) {}

  async findByToken(token: string): Promise<RefreshTokenData | null> {
    const data = await this.prisma.refreshToken.findUnique({
      where: { token },
    });

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

  async create(data: {
    userId: bigint;
    token: string;
    deviceInfo?: string;
    ipAddress?: string;
    expiresAt: Date;
  }): Promise<RefreshTokenData> {
    const created = await this.prisma.refreshToken.create({
      data: {
        userId: data.userId,
        token: data.token,
        deviceInfo: data.deviceInfo,
        ipAddress: data.ipAddress,
        expiresAt: data.expiresAt,
      },
    });

    return this.toDomain(created);
  }

  async revoke(token: string): Promise<void> {
    await this.prisma.refreshToken.update({
      where: { token },
      data: { revokedAt: new Date() },
    });
  }

  async revokeAllByUserId(userId: bigint): Promise<void> {
    await this.prisma.refreshToken.updateMany({
      where: {
        userId,
        revokedAt: null,
      },
      data: { revokedAt: new Date() },
    });
  }

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

    return result.count;
  }

  async countActiveByUserId(userId: bigint): Promise<number> {
    return this.prisma.refreshToken.count({
      where: {
        userId,
        revokedAt: null,
        expiresAt: { gt: new Date() },
      },
    });
  }

  private toDomain(data: any): RefreshTokenData {
    return {
      id: data.id,
      userId: data.userId,
      token: data.token,
      deviceInfo: data.deviceInfo,
      ipAddress: data.ipAddress,
      expiresAt: data.expiresAt,
      createdAt: data.createdAt,
      revokedAt: data.revokedAt,
    };
  }
}
