import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { MailService } from 'src/mail/mail.service';
import { SmsService } from 'src/sms/sms.service';
import { applyFiltersToBuilder } from 'src/utils';
import { Repository } from 'typeorm';
import { ErrorService } from '../../error/error.service';
import { ReplyCooperationDto, SenderType } from './dto/reply-cooperation.dto';
import { UpdateCooperationDto } from './dto/update-cooperation.dto';
import { CooperationEntity } from './entities/cooperation.entity';

@Injectable()
export class CooperationService {
  constructor(
    @InjectRepository(CooperationEntity)
    private CooperationsRepository: Repository<CooperationEntity>,
    private error: ErrorService,
    private sms: SmsService,
    private mail: MailService,
  ) {}

  /**
   * -------------------------------------------------------
   */
  async statistic() {
    const unReaded = await this.CooperationsRepository.count({
      isReade: false,
    });
    return {
      unReaded,
    };
  }

  /**
   * -------------------------------------------------------
   */
  async getAll(filters = null) {
    let builder =
      this.CooperationsRepository.createQueryBuilder('cooperations');

    builder.addSelect('cooperations.isReade', 'isReaded');
    builder = applyFiltersToBuilder(builder, filters);

    return await builder.getMany();
  }

  /**
   * -------------------------------------------------------
   */
  async updateById(id: number, dto: UpdateCooperationDto) {
    return await this._update(id, { isReade: dto.isReaded });
  }

  /**
   * -------------------------------------------------------
   */
  private async _update(id: number, values: any) {
    return await this.CooperationsRepository.createQueryBuilder()
      .update()
      .set({ ...values, updatedAt: new Date() })
      .where({ id })
      .execute();
  }

  /**
   * -------------------------------------------------------
   */
  async replyById(id: number, dto: ReplyCooperationDto) {
    const cooperation = await this.getById(id);

    if (!cooperation) {
      this.error.unprocessableEntity(['شناسه پیام ورودی یافت نشد']);
    }
    if (dto.senderType === SenderType.SMS && !cooperation.mobile) {
      this.error.unprocessableEntity([
        'امکان ارسال پاسخ از طریق SMS وجود ندارد به این دلیل که کاربر شماره موبایلی ثبت نکرده است',
      ]);
    }
    if (dto.senderType === SenderType.MAIL && !cooperation.email) {
      this.error.unprocessableEntity([
        'امکان ارسال پاسخ از طریق ایمیل وجود ندارد به این دلیل که کاربر ایمیلی برای این پیام ثبت نکرده است',
      ]);
    }

    await this._update(id, { answer: dto.answer });

    // Sending the answer via sms
    if (
      dto.senderType === SenderType.SMS ||
      (dto.senderType === SenderType.ALL && cooperation.mobile)
    ) {
      await this.sms.send(
        cooperation.mobile,
        dto.answer.replace(/<[^>]+>/g, ''),
      );
    }

    // Sending the answer via email
    if (
      dto.senderType === SenderType.MAIL ||
      (dto.senderType === SenderType.ALL && cooperation.email)
    ) {
      await this.mail.sendReplyCooperate(cooperation.email, dto.answer);
    }

    return true;
  }

  /**
   * -------------------------------------------------------
   */
  async getById(id: number) {
    return await this.CooperationsRepository.createQueryBuilder('cooperation')
      .where({ id })
      .addSelect('cooperation.answer IS NOT NULL', 'isAnswered')
      .addSelect('cooperation.isReade', 'isReaded')
      .getOne();
  }
}
