import { Notification as BlockletNotification } from '@blocklet/sdk';

import type { BaseEmailTemplate, BaseEmailTemplateType } from './template/base';
import { CheckoutSession, CreditGrant, Invoice, Meter, MeterEvent, Subscription } from '../../store/models';
import { getNotificationSettings, shouldSendSystemNotification } from '../setting';
import logger from '../logger';
import { events } from '../event';
import { createFlexibleEvent } from '../audit';

export class Notification {
  template: BaseEmailTemplate;
  type?: string;
  constructor(template: BaseEmailTemplate, type?: string) {
    this.template = template;
    if (type) {
      this.type = type;
    }
  }

  async send(allowUnsubscribe: boolean = false) {
    const template: BaseEmailTemplateType | null = await this.template.getTemplate();

    if (!template) {
      return;
    }

    const context = await this.template.getContext();
    const { userDid } = context;
    try {
      const entity = await this.getEntityFromOptions(this.template.options);
      if (entity) {
        const settings = await getNotificationSettings(entity);
        const shouldSend = shouldSendSystemNotification(this.type as string, settings);
        if (!shouldSend) {
          logger.info('Notification will not be sent', {
            type: this.type,
            entity,
          });
          try {
            await createFlexibleEvent('manual.notification', 'notification', entity.id, {
              type: this.type,
              data: {
                entity,
                userDid,
                context,
              },
            });
          } catch (error) {
            logger.error('Create flexible event error', error);
            events.emit('manual.notification', {
              type: this.type,
              data: {
                entity,
                userDid,
                context,
              },
            });
          }
          return;
        }
      }
    } catch (error) {
      logger.error('Check notification settings error', error);
    }

    await BlockletNotification.sendToUser(userDid, template as any, { allowUnsubscribe });
  }
  private async getEntityFromOptions(options: Record<string, any>) {
    if (options.subscriptionId) {
      const subscription = await Subscription.findByPk(options.subscriptionId);
      if (subscription) {
        return { subscription, id: subscription.id };
      }
    }

    if (options.invoiceId) {
      const invoice = await Invoice.findByPk(options.invoiceId);
      if (invoice) {
        return { invoice, id: invoice.id };
      }
    }

    if (options.checkoutSessionId) {
      const checkoutSession = await CheckoutSession.findByPk(options.checkoutSessionId);
      if (checkoutSession) {
        return { checkoutSession, id: checkoutSession.id };
      }
    }

    if (options.creditGrantId) {
      const creditGrant = await CreditGrant.findByPk(options.creditGrantId);
      if (creditGrant) {
        const meter = await Meter.findOne({
          where: {
            currency_id: creditGrant.currency_id,
            status: 'active',
          },
        });
        if (meter) {
          return { meter, id: meter.id };
        }
      }
    }
    if (options.meterEventName) {
      const meterEvent = await MeterEvent.findOne({
        where: {
          event_name: options.meterEventName,
        },
      });
      if (meterEvent) {
        const meter = await Meter.getMeterByEventName(meterEvent.event_name);
        if (meter) {
          return { meter, id: meter.id };
        }
      }
    }
    return null;
  }
}
