import { logger } from '@goodgo/logger';
import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
import { Request } from 'express';

import { getPrismaClient } from '../../config/database.config';
import { auditService } from '../../core/events/audit.service';


/**
 * EN: Change Password Service
 * VI: Service đổi mật khẩu
 */
export class ChangePasswordService {
  private prisma: PrismaClient;

  constructor() {
    this.prisma = getPrismaClient();
  }

  /**
   * EN: Change user password
   * VI: Đổi mật khẩu người dùng
   */
  async changePassword(
    userId: string,
    currentPassword: string,
    newPassword: string,
    req?: Request
  ): Promise<void> {
    // Get user
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
    });

    if (!user || !user.passwordHash) {
      throw new Error('User not found or password not set');
    }

    // Verify current password
    const isValid = await bcrypt.compare(currentPassword, user.passwordHash);
    if (!isValid) {
      if (req) {
        await auditService.logFromRequest(req, 'PASSWORD_CHANGE_FAILED', {
          userId,
          success: false,
          errorMessage: 'Invalid current password',
        });
      }
      throw new Error('Current password is incorrect');
    }

    // Hash new password
    const newPasswordHash = await bcrypt.hash(newPassword, 12);

    // Update password
    await this.prisma.user.update({
      where: { id: userId },
      data: { passwordHash: newPasswordHash },
    });

    // Revoke all refresh tokens for security
    await this.prisma.refreshToken.updateMany({
      where: { userId },
      data: { revokedAt: new Date() },
    });

    // Audit log
    if (req) {
      await auditService.logFromRequest(req, 'PASSWORD_CHANGED', {
        userId,
        success: true,
      });
    }

    logger.info('Password changed', { userId });
  }
}

export const changePasswordService = new ChangePasswordService();
