const { User } = require('../models/user');
const ListaInvitiEmail = require('../models/listainvitiemail');
const tools = require('../tools/general');
const shared_consts = require('../tools/shared_nodejs');
const server_constants = require('../tools/server_constants');
const reg = require('../reg/registration');
const telegrambot = require('../telegram/telegrambot');
const sendemail = require('../sendemail');

class RegistrationService {
  /**
   * Register a new user
   */
  async registerUser(userData, req) {
    try {
      const user = new User(userData);

      // Set default aportador if needed
      this._normalizeAportadorSolidario(user);

      // Generate registration link
      user.linkreg = reg.getlinkregByEmail(user.idapp, user.email, user.username);
      user.verified_email = false;

      // Check if user is part of an invitation
      await this._checkEmailInvitation(user);

      // Set timestamps
      user.lasttimeonline = new Date();
      user.date_reg = new Date();
      user.aportador_iniziale = user.aportador_solidario;

      // Handle registration token
      const regexpire = req.body['regexpire'];
      const skipVerification = regexpire ? await User.getifRegTokenIsValid(user.idapp, regexpire) : false;

      if (!tools.getAskToVerifyReg(user.idapp) || skipVerification) {
        user.verified_by_aportador = true;
      }

      // Set default group
      const idMyGroupSite = tools.getidMyGroupBySite(user.idapp);
      user.idMyGroup = idMyGroupSite || '';

      // Validate aportador (inviter)
      const aportadorValidation = await this._validateAportador(user);
      if (aportadorValidation.error) {
        return aportadorValidation;
      }

      // Check for existing user
      const existingUserCheck = await this._checkExistingUser(user);
      if (existingUserCheck.error) {
        return existingUserCheck;
      }

      // Handle already registered but not verified case
      if (existingUserCheck.notYetVerified) {
        return await this._handleNotYetVerified(user, existingUserCheck.existingUser, req);
      }

      // Save new user
      return await this._saveNewUser(user, req, regexpire);
    } catch (error) {
      console.error('Error in registerUser:', error.message);
      return {
        error: true,
        code: server_constants.RIS_CODE_ERR,
        message: error.message,
      };
    }
  }

  /**
   * Normalize aportador solidario field
   * @private
   */
  _normalizeAportadorSolidario(user) {
    if (user.aportador_solidario === 'tuo_username' || user.aportador_solidario === '{username}') {
      user.aportador_solidario = 'surya1977';
    }

    user.aportador_solidario = user.aportador_solidario.trim().replace('@', '');
  }

  /**
   * Check if email is part of an invitation
   * @private
   */
  async _checkEmailInvitation(user) {
    const invitation = await ListaInvitiEmail.findOne({ email: user.email });

    if (invitation) {
      user.verified_email = true;
      user.verified_by_aportador = true;

      invitation.registered = true;
      invitation.userIdRegistered = user._id;
      await invitation.save();
    }
  }

  /**
   * Validate aportador solidario (inviter)
   * @private
   */
  async _validateAportador(user) {
    let id_aportador = await User.getIdByUsername(user.idapp, user.aportador_solidario);

    // Try to find by Telegram username if not found
    if (!id_aportador) {
      const userAportador = await User.getUserByUsernameTelegram(user.idapp, user.aportador_solidario);

      if (userAportador) {
        id_aportador = userAportador._id;
        user.aportador_solidario = userAportador.username;
      }
    }

    // Get correct username (case-sensitive)
    if (id_aportador) {
      user.aportador_solidario = await User.getRealUsernameByUsername(user.idapp, user.aportador_solidario);
    }

    // Check if aportador is required and valid
    if (!id_aportador && tools.getAskToVerifyReg(user.idapp)) {
      const msg = `Il link di registrazione non sembra risultare valido.<br>invitante: ${user.aportador_solidario}<br>username: ${user.username}`;

      await telegrambot.sendMsgTelegramToTheManagers(user.idapp, msg);

      return {
        error: true,
        code: server_constants.RIS_CODE_USER_APORTADOR_NOT_VALID,
        message: msg,
      };
    }

    return { error: false, id_aportador };
  }

  /**
   * Check if user already exists
   * @private
   */
  async _checkExistingUser(user) {
    let notYetVerified = false;
    let existingUser = null;

    // Check by credentials (username + password)
    const userByCredentials = await User.findByCredentials(user.idapp, user.username, user.password, true);

    // Check by username
    const userByUsername = await User.findByUsername(user.idapp, user.username);

    if (userByUsername) {
      // Check if it's a user waiting for verification
      if (tools.getAskToVerifyReg(userByUsername.idapp)) {
        if (!userByUsername.verified_by_aportador && userByUsername.profile.teleg_id > 0 && userByCredentials) {
          notYetVerified = true;
          existingUser = userByCredentials;
        }
      }

      if (!notYetVerified) {
        return {
          error: true,
          code: server_constants.RIS_CODE_USERNAME_ALREADY_EXIST,
          message: 'Username già esistente',
        };
      }
    }

    // Check by email (only if not waiting for verification)
    if (!notYetVerified) {
      const userByEmail = await User.findByEmail(user.idapp, user.email);

      if (userByEmail) {
        return {
          error: true,
          code: server_constants.RIS_CODE_EMAIL_ALREADY_EXIST,
          message: 'Email già esistente',
        };
      }

      // Check by cell phone + name + surname
      const userByCell = await User.findByCellAndNameSurname(user.idapp, user.profile.cell, user.name, user.surname);

      if (userByCell && user.name !== '' && user.surname !== '' && user.profile.cell !== '') {
        console.log('UTENTE GIA ESISTENTE:', user);
        return {
          error: true,
          code: server_constants.RIS_CODE_USER_ALREADY_EXIST,
          message: 'Utente già registrato',
        };
      }
    }

    return {
      error: false,
      notYetVerified,
      existingUser,
    };
  }

  /**
   * Handle user that registered but not yet verified
   * @private
   */
  async _handleNotYetVerified(newUser, existingUser, req) {
    const id_aportador = await User.getIdByUsername(newUser.idapp, newUser.aportador_solidario);

    if (id_aportador) {
      // Update aportador for existing user
      await User.setaportador_solidario(newUser.idapp, newUser.username, newUser.aportador_solidario);

      const myuser = await User.findOne({ _id: existingUser._id });

      
      if (myuser) {
        // Ask confirmation from inviter
        await telegrambot.askConfirmationUser(myuser.idapp, shared_consts.CallFunz.REGISTRATION, myuser);

        const { token, refreshToken, browser_random } = await myuser.generateAuthToken(req);

        return {
          error: false,
          token,
          refreshToken,
          browser_random,
          user: myuser,
        };
      }
    }

    return {
      error: true,
      code: server_constants.RIS_CODE_ERR,
      message: 'Errore nella registrazione',
    };
  }

  /**
   * Save new user and send notifications
   * @private
   */
  async _saveNewUser(user, req, regexpire = '') {
    await user.save();

    const savedUser = await User.findByUsername(user.idapp, user.username, false);

    if (!savedUser) {
      return {
        error: true,
        code: server_constants.RIS_CODE_ERR,
        message: "Errore nel salvare l'utente",
      };
    }

    // Generate tokens
    const { token, refreshToken, browser_random } = await savedUser.generateAuthToken(req);

    if (!savedUser.verified_by_aportador) {
      // Send confirmation request to inviter
      await telegrambot.askConfirmationUser(
        user.idapp,
        shared_consts.CallFunz.REGISTRATION,
        user,
        '',
        '',
        '',
        '',
        regexpire
      );
    }

    // Send registration email
    await sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg);

    return {
      error: false,
      token,
      refreshToken,
      browser_random,
      user: savedUser,
    };
  }
}

module.exports = RegistrationService;
