const BaseModel = require('./BaseModel');
const crypto = require('crypto');
const { promisify } = require('util');
const randomBytesAsync = promisify(crypto.randomBytes);

class PasswordReset extends BaseModel {
  constructor() {
    super('password_resets');
  }

  async createToken(email, expiresInHours = 1) {
    // Generate a random token
    const token = (await randomBytesAsync(32)).toString('hex');
    
    // Calculate expiration time
    const expiresAt = new Date();
    expiresAt.setHours(expiresAt.getHours() + expiresInHours);
    
    // Invalidate any existing tokens for this email
    await this.db.query(
      'UPDATE password_resets SET is_used = 1 WHERE email = ? AND is_used = 0',
      [email]
    );
    
    // Create new token
    const [result] = await this.db.query(
      'INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)',
      [email, token, expiresAt]
    );
    
    return {
      id: result.insertId,
      email,
      token,
      expires_at: expiresAt
    };
  }

  async validateToken(email, token) {
    const [rows] = await this.db.query(
      `SELECT * FROM password_resets 
       WHERE email = ? AND token = ? AND is_used = 0 AND expires_at > NOW()
       ORDER BY created_at DESC LIMIT 1`,
      [email, token]
    );
    
    return rows[0] || null;
  }

  async markAsUsed(id) {
    await this.db.query(
      'UPDATE password_resets SET is_used = 1 WHERE id = ?',
      [id]
    );
    return true;
  }

  async cleanupExpiredTokens() {
    // Mark all expired tokens as used
    await this.db.query(
      'UPDATE password_resets SET is_used = 1 WHERE expires_at <= NOW() AND is_used = 0'
    );
    
    // Optionally delete old used tokens (older than 7 days)
    await this.db.query(
      'DELETE FROM password_resets WHERE is_used = 1 AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)'
    );
    
    return true;
  }
}

module.exports = new PasswordReset();
