const db = require('../db/models');
const UsersDBApi = require('../db/api/users');
const { createEntityService } = require('../factories/service.factory');
const ValidationError = require('./notifications/errors/validation');
const config = require('../config');
const AuthService = require('./auth');

// Generate base service from factory
const BaseUsersService = createEntityService(UsersDBApi, { entityName: 'Users' });

/**
 * Users service with email invitation functionality
 * Extends factory-generated service with custom user logic
 */
class UsersService extends BaseUsersService {
  /**
   * Create user with email validation and optional invitation
   */
  static async create(data, currentUser, sendInvitationEmails = true, host) {
    const transaction = await db.sequelize.transaction();
    const email = data.email;

    try {
      if (!email) {
        throw new ValidationError('iam.errors.emailRequired');
      }

      const existingUser = await UsersDBApi.findBy({ email }, { transaction });
      if (existingUser) {
        throw new ValidationError('iam.errors.userAlreadyExists');
      }

      await UsersDBApi.create({ data }, { currentUser, transaction });
      await transaction.commit();

      // Send invitation email after successful commit
      if (sendInvitationEmails) {
        AuthService.sendPasswordResetEmail(email, 'invitation', host);
      }
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  /**
   * Remove user with self-deletion and permission checks
   */
  static async remove(id, currentUser) {
    if (currentUser.id === id) {
      throw new ValidationError('iam.errors.deletingHimself');
    }

    if (currentUser.app_role?.name !== config.roles.admin) {
      throw new ValidationError('errors.forbidden.message');
    }

    // Delegate to parent (factory) implementation
    return super.remove(id, currentUser);
  }
}

module.exports = UsersService;
