// import { Service, Inject } from 'typedi';
// import moment from 'moment';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// import events from '@/subscribers/events';
// import {
//   ISaleInvoice,
//   ISaleInvoiceSmsDetailsDTO,
//   ISaleInvoiceSmsDetails,
//   SMS_NOTIFICATION_KEY,
//   InvoiceNotificationType,
//   ICustomer,
// } from '@/interfaces';
// import SmsNotificationsSettingsService from '@/services/Settings/SmsNotificationsSettings';
// import { formatSmsMessage, formatNumber } from 'utils';
// import { TenantMetadata } from '@/system/models';
// import SaleNotifyBySms from '../SaleNotifyBySms';
// import { ServiceError } from '@/exceptions';
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
// import { ERRORS } from './constants';
// import { CommandSaleInvoiceValidators } from './CommandSaleInvoiceValidators';

// @Service()
// export class SaleInvoiceNotifyBySms {
//   @Inject()
//   private tenancy: HasTenancyService;

//   @Inject()
//   private eventPublisher: EventPublisher;

//   @Inject()
//   private smsNotificationsSettings: SmsNotificationsSettingsService;

//   @Inject()
//   private saleSmsNotification: SaleNotifyBySms;

//   @Inject()
//   private validators: CommandSaleInvoiceValidators;

//   /**
//    * Notify customer via sms about sale invoice.
//    * @param {number} tenantId - Tenant id.
//    * @param {number} saleInvoiceId - Sale invoice id.
//    */
//   public notifyBySms = async (
//     tenantId: number,
//     saleInvoiceId: number,
//     invoiceNotificationType: InvoiceNotificationType
//   ) => {
//     const { SaleInvoice } = this.tenancy.models(tenantId);

//     // Retrieve the sale invoice or throw not found service error.
//     const saleInvoice = await SaleInvoice.query()
//       .findById(saleInvoiceId)
//       .withGraphFetched('customer');

//     // Validates the givne invoice existance.
//     this.validators.validateInvoiceExistance(saleInvoice);

//     // Validate the customer phone number existance and number validation.
//     this.saleSmsNotification.validateCustomerPhoneNumber(
//       saleInvoice.customer.personalPhone
//     );
//     // Transformes the invoice notification key to sms notification key.
//     const notificationKey = this.transformDTOKeyToNotificationKey(
//       invoiceNotificationType
//     );
//     // Triggers `onSaleInvoiceNotifySms` event.
//     await this.eventPublisher.emitAsync(events.saleInvoice.onNotifySms, {
//       tenantId,
//       saleInvoice,
//     });
//     // Formattes the sms message and sends sms notification.
//     await this.sendSmsNotification(tenantId, notificationKey, saleInvoice);

//     // Triggers `onSaleInvoiceNotifySms` event.
//     await this.eventPublisher.emitAsync(events.saleInvoice.onNotifiedSms, {
//       tenantId,
//       saleInvoice,
//     });
//     return saleInvoice;
//   };

//   /**
//    * Notify invoice details by sms notification after invoice creation.
//    * @param {number} tenantId
//    * @param {number} saleInvoiceId
//    * @returns {Promise<void>}
//    */
//   public notifyDetailsBySmsAfterCreation = async (
//     tenantId: number,
//     saleInvoiceId: number
//   ): Promise<void> => {
//     const notification = this.smsNotificationsSettings.getSmsNotificationMeta(
//       tenantId,
//       SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//     );
//     // Can't continue if the sms auto-notification is not enabled.
//     if (!notification.isNotificationEnabled) return;

//     await this.notifyBySms(tenantId, saleInvoiceId, 'details');
//   };

//   /**
//    * Sends SMS notification.
//    * @param {ISaleInvoice} invoice
//    * @param {ICustomer} customer
//    * @returns {Promise<void>}
//    */
//   private sendSmsNotification = async (
//     tenantId: number,
//     notificationType:
//       | SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//       | SMS_NOTIFICATION_KEY.SALE_INVOICE_REMINDER,
//     invoice: ISaleInvoice & { customer: ICustomer }
//   ): Promise<void> => {
//     const smsClient = this.tenancy.smsClient(tenantId);
//     const tenantMetadata = await TenantMetadata.query().findOne({ tenantId });

//     // Formates the given sms message.
//     const message = this.formattedInvoiceDetailsMessage(
//       tenantId,
//       notificationType,
//       invoice,
//       tenantMetadata
//     );
//     const phoneNumber = invoice.customer.personalPhone;

//     // Run the send sms notification message job.
//     await smsClient.sendMessageJob(phoneNumber, message);
//   };

//   /**
//    * Formates the invoice details sms message.
//    * @param {number} tenantId
//    * @param {ISaleInvoice} invoice
//    * @param {ICustomer} customer
//    * @returns {string}
//    */
//   private formattedInvoiceDetailsMessage = (
//     tenantId: number,
//     notificationKey:
//       | SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//       | SMS_NOTIFICATION_KEY.SALE_INVOICE_REMINDER,
//     invoice: ISaleInvoice,
//     tenantMetadata: TenantMetadata
//   ): string => {
//     const notification = this.smsNotificationsSettings.getSmsNotificationMeta(
//       tenantId,
//       notificationKey
//     );
//     return this.formatInvoiceDetailsMessage(
//       notification.smsMessage,
//       invoice,
//       tenantMetadata
//     );
//   };

//   /**
//    * Formattees the given invoice details sms message.
//    * @param {string} smsMessage
//    * @param {ISaleInvoice} invoice
//    * @param {ICustomer} customer
//    * @param {TenantMetadata} tenantMetadata
//    */
//   private formatInvoiceDetailsMessage = (
//     smsMessage: string,
//     invoice: ISaleInvoice & { customer: ICustomer },
//     tenantMetadata: TenantMetadata
//   ) => {
//     const formattedDueAmount = formatNumber(invoice.dueAmount, {
//       currencyCode: invoice.currencyCode,
//     });
//     const formattedAmount = formatNumber(invoice.balance, {
//       currencyCode: invoice.currencyCode,
//     });

//     return formatSmsMessage(smsMessage, {
//       InvoiceNumber: invoice.invoiceNo,
//       ReferenceNumber: invoice.referenceNo,
//       CustomerName: invoice.customer.displayName,
//       DueAmount: formattedDueAmount,
//       DueDate: moment(invoice.dueDate).format('YYYY/MM/DD'),
//       Amount: formattedAmount,
//       CompanyName: tenantMetadata.name,
//     });
//   };

//   /**
//    * Retrieve the SMS details of the given invoice.
//    * @param {number} tenantId - Tenant id.
//    * @param {number} saleInvoiceId - Sale invoice id.
//    */
//   public smsDetails = async (
//     tenantId: number,
//     saleInvoiceId: number,
//     invoiceSmsDetailsDTO: ISaleInvoiceSmsDetailsDTO
//   ): Promise<ISaleInvoiceSmsDetails> => {
//     const { SaleInvoice } = this.tenancy.models(tenantId);

//     // Retrieve the sale invoice or throw not found service error.
//     const saleInvoice = await SaleInvoice.query()
//       .findById(saleInvoiceId)
//       .withGraphFetched('customer');

//     // Validates the sale invoice existance.
//     this.validateSaleInvoiceExistance(saleInvoice);

//     // Current tenant metadata.
//     const tenantMetadata = await TenantMetadata.query().findOne({ tenantId });

//     // Transformes the invoice notification key to sms notification key.
//     const notificationKey = this.transformDTOKeyToNotificationKey(
//       invoiceSmsDetailsDTO.notificationKey
//     );
//     // Formates the given sms message.
//     const smsMessage = this.formattedInvoiceDetailsMessage(
//       tenantId,
//       notificationKey,
//       saleInvoice,
//       tenantMetadata
//     );

//     return {
//       customerName: saleInvoice.customer.displayName,
//       customerPhoneNumber: saleInvoice.customer.personalPhone,
//       smsMessage,
//     };
//   };

//   /**
//    * Transformes the invoice notification key DTO to notification key.
//    * @param {string} invoiceNotifKey
//    * @returns {SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//    *   | SMS_NOTIFICATION_KEY.SALE_INVOICE_REMINDER}
//    */
//   private transformDTOKeyToNotificationKey = (
//     invoiceNotifKey: string
//   ):
//     | SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//     | SMS_NOTIFICATION_KEY.SALE_INVOICE_REMINDER => {
//     const invoiceNotifKeyPairs = {
//       details: SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS,
//       reminder: SMS_NOTIFICATION_KEY.SALE_INVOICE_REMINDER,
//     };
//     return (
//       invoiceNotifKeyPairs[invoiceNotifKey] ||
//       SMS_NOTIFICATION_KEY.SALE_INVOICE_DETAILS
//     );
//   };

//   /**
//    * Validates the sale invoice existance.
//    * @param {ISaleInvoice|null} saleInvoice
//    */
//   private validateSaleInvoiceExistance(saleInvoice: ISaleInvoice | null) {
//     if (!saleInvoice) {
//       throw new ServiceError(ERRORS.SALE_INVOICE_NOT_FOUND);
//     }
//   }
// }
