// src/auth/repositories/refresh-token.repository.ts
import { DataSource, Repository } from 'typeorm';
import { RefreshToken } from '@/entities/refresh-token.entity';
import { Injectable, NotFoundException } from '@nestjs/common';

@Injectable()
export class RefreshTokenRepository extends Repository<RefreshToken> {
  constructor(private dataSource: DataSource) {
    super(RefreshToken, dataSource.createEntityManager());
  }

  async createRefreshToken(user: any, ttl: number): Promise<RefreshToken> {
    const refreshToken = this.create();
    refreshToken.userId = user.id;
    refreshToken.isActive = true;
    refreshToken.expiresAt = new Date(Date.now() + ttl);
    
    // Generate token
    refreshToken.token = await this.generateToken();
    
    return await this.save(refreshToken);
  }

  async findTokenById(id: string): Promise<RefreshToken> {
    const token = await this.findOne({ where: { id } });
    if (!token) {
      throw new NotFoundException(`Refresh token with ID ${id} not found`);
    }
    return token;
  }

  async findTokenByToken(token: string): Promise<RefreshToken> {
    const refreshToken = await this.findOne({ 
      where: { token }, 
      relations: ['user'] 
    });
    
    if (!refreshToken) {
      throw new NotFoundException('Refresh token not found');
    }
    
    return refreshToken;
  }

  async revokeToken(id: string): Promise<void> {
    await this.update(id, { isActive: false });
  }

  async revokeAllTokensForUser(userId: string): Promise<void> {
    await this.update(
      { userId, isActive: true }, 
      { isActive: false }
    );
  }

  async isTokenActive(token: string): Promise<boolean> {
    try {
      const refreshToken = await this.findTokenByToken(token);
      return refreshToken.isActive && refreshToken.expiresAt > new Date();
    } catch {
      return false;
    }
  }

  async deleteExpiredTokens(): Promise<void> {
    await this.createQueryBuilder()
      .delete()
      .from(RefreshToken)
      .where('expiresAt < :currentDate', { currentDate: new Date() })
      .execute();
  }

  private async generateToken(): Promise<string> {
    const crypto = require('crypto');
    return crypto.randomBytes(40).toString('hex');
  }
}