import { dataSource } from "../../../data-source";
import { communication } from "../../../entity/club/member/communication";
import InternalException from "../../../exceptions/internalException";
import {
  CreateCommunicationCommand,
  DeleteCommunicationCommand,
  UpdateCommunicationCommand,
} from "./communicationCommand";

export default abstract class CommunicationCommandHandler {
  /**
   * @description create communication
   * @param {CreateCommunicationCommand} createCommunication
   * @returns {Promise<number>}
   */
  static async create(createCommunication: CreateCommunicationCommand): Promise<number> {
    let insertId = -1;
    return await dataSource
      .transaction(async (manager) => {
        await manager
          .createQueryBuilder()
          .insert()
          .into(communication)
          .values({
            preferred: createCommunication.preferred,
            isSMSAlarming: createCommunication.isSMSAlarming,
            isSendNewsletter: createCommunication.isSendNewsletter,
            mobile: createCommunication.mobile,
            email: createCommunication.email,
            postalCode: createCommunication.postalCode,
            city: createCommunication.city,
            street: createCommunication.street,
            streetNumber: createCommunication.streetNumber,
            streetNumberAddition: createCommunication.streetNumberAddition,
            memberId: createCommunication.memberId,
            typeId: createCommunication.typeId,
          })
          .execute()
          .then((result) => {
            insertId = result.identifiers[0].id;
          });

        await manager
          .createQueryBuilder()
          .update(communication)
          .set({
            isSendNewsletter: false,
          })
          .where("memberId = :memberId", { memberId: createCommunication.memberId })
          .andWhere("id <> :id", { id: insertId })
          .execute();
      })
      .then(() => {
        return insertId;
      })
      .catch((err) => {
        throw new InternalException("Failed creating communication", err);
      });
  }

  /**
   * @description update communication
   * @param {UpdateCommunicationCommand} updateCommunication
   * @returns {Promise<void>}
   */
  static async update(updateCommunication: UpdateCommunicationCommand): Promise<void> {
    return await dataSource
      .transaction(async (manager) => {
        await manager
          .createQueryBuilder()
          .update(communication)
          .set({
            preferred: updateCommunication.preferred,
            isSMSAlarming: updateCommunication.isSMSAlarming,
            isSendNewsletter: updateCommunication.isSendNewsletter,
            mobile: updateCommunication.mobile,
            email: updateCommunication.email,
            postalCode: updateCommunication.postalCode,
            city: updateCommunication.city,
            street: updateCommunication.street,
            streetNumber: updateCommunication.streetNumber,
            streetNumberAddition: updateCommunication.streetNumberAddition,
          })
          .where("id = :id", { id: updateCommunication.id })
          .andWhere("memberId = :memberId", { memberId: updateCommunication.memberId })
          .execute();

        await manager
          .createQueryBuilder()
          .update(communication)
          .set({
            isSendNewsletter: false,
          })
          .where("memberId = :memberId", { memberId: updateCommunication.memberId })
          .andWhere("id <> :id", { id: updateCommunication.id })
          .execute();
      })
      .then(() => {})
      .catch((err) => {
        throw new InternalException("Failed updating communication", err);
      });
  }

  /**
   * @description delete communication
   * @param {DeleteCommunicationCommand} deleteCommunication
   * @returns {Promise<void>}
   */
  static async delete(deleteCommunication: DeleteCommunicationCommand): Promise<void> {
    return await dataSource
      .createQueryBuilder()
      .delete()
      .from(communication)
      .where("id = :id", { id: deleteCommunication.id })
      .andWhere("memberId = :memberId", { memberId: deleteCommunication.memberId })
      .execute()
      .then(() => {})
      .catch((err) => {
        throw new InternalException("Failed deleting communication", err);
      });
  }
}