import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { MailerService } from '../mailer/mailer.service';
import { CreateTempUserDto } from './dto/create-temp-user.dto';
import { TempUser } from './temp-user.schema';
import * as ejs from 'ejs';
import { ITempUser } from './temp-user.interface';

@Injectable()
export class TempUserService {
  constructor(
    private readonly mailerService: MailerService,
    @InjectModel(TempUser.name) private tempUserModel: Model<ITempUser>
  ) {}

  public async create(createTempUser: CreateTempUserDto, structureName: string): Promise<TempUser> {
    const userInDb = await this.findOne(createTempUser.email);
    if (userInDb) {
      throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);
    }
    const createUser = await this.tempUserModel.create(createTempUser);
    // Send email
    this.sendUserMail(createUser, structureName);
    return this.findOne(createTempUser.email);
  }

  public async findOne(mail: string): Promise<TempUser> {
    return this.tempUserModel.findOne({ email: mail });
  }

  public async findById(id: string): Promise<TempUser> {
    return this.tempUserModel.findById(Types.ObjectId(id));
  }

  public async delete(mail: string): Promise<TempUser> {
    const userInDb = await this.findOne(mail);
    if (!userInDb) {
      throw new HttpException('User does not exists', HttpStatus.BAD_REQUEST);
    }
    this.tempUserModel.deleteOne({ email: mail });
    return userInDb;
  }

  public async updateStructureLinked(createTempUser: CreateTempUserDto): Promise<TempUser> {
    const userInDb = await this.tempUserModel
      .find({
        $and: [
          {
            email: createTempUser.email,
          },
          {
            pendingStructuresLink: { $in: [createTempUser.pendingStructuresLink[0]] },
          },
        ],
      })
      .exec();
    if (userInDb.length > 0) {
      throw new HttpException('User already linked', HttpStatus.UNPROCESSABLE_ENTITY);
    }
    return this.tempUserModel
      .updateOne(
        { email: createTempUser.email },
        { $push: { pendingStructuresLink: createTempUser.pendingStructuresLink[0] } }
      )
      .exec();
  }

  /**
   * Send email in order to tell the user that an account is alreday fill with his structure info.
   * @param user User
   */
  private async sendUserMail(user: ITempUser, structureName: string): Promise<any> {
    const config = this.mailerService.config;
    const ejsPath = this.mailerService.getTemplateLocation(config.templates.tempUserRegistration.ejs);
    const jsonConfig = this.mailerService.loadJsonConfig(config.templates.tempUserRegistration.json);

    const html = await ejs.renderFile(ejsPath, {
      config,
      id: user._id,
      name: structureName,
    });
    this.mailerService.send(user.email, jsonConfig.subject, html);
  }
}