import crypto from 'crypto';
import { prisma } from '../config/database';
import { logger } from '../utils/logger';

/** Hash a token with SHA-256 for storage (raw token is sent to user, hash is stored in DB). */
function hashToken(token: string): string {
  return crypto.createHash('sha256').update(token).digest('hex');
}

export const verificationTokenService = {
  async createToken(userId: string): Promise<string> {
    // Delete any existing tokens for this user
    await prisma.emailVerificationToken.deleteMany({ where: { userId } });

    const rawToken = crypto.randomBytes(32).toString('hex');
    const tokenHash = hashToken(rawToken);
    const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours

    await prisma.emailVerificationToken.create({
      data: { userId, token: tokenHash, expiresAt },
    });

    // 2026-04-12: userId removed from log (see password-reset-token.service).
    logger.info('Verification token created');
    return rawToken; // Send raw token in email; DB stores only the hash
  },

  async verifyToken(token: string): Promise<{ valid: boolean; userId?: string; error?: string }> {
    const tokenHash = hashToken(token);
    const record = await prisma.emailVerificationToken.findUnique({ where: { token: tokenHash } });

    if (!record) {
      return { valid: false, error: 'Invalid or expired verification token' };
    }

    if (record.expiresAt < new Date()) {
      await prisma.emailVerificationToken.delete({ where: { id: record.id } });
      return { valid: false, error: 'Verification token has expired' };
    }

    // Delete the token after successful verification
    await prisma.emailVerificationToken.delete({ where: { id: record.id } });

    return { valid: true, userId: record.userId };
  },

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

    if (result.count > 0) {
      logger.info(`Cleaned up ${result.count} expired verification tokens`);
    }

    return result.count;
  },
};
