import dayjs from 'dayjs';
/* eslint-disable no-console */
import { Op } from 'sequelize';

import type { SubscriptionTrialWillEndEmailTemplateOptions } from '../libs/notification/template/subscription-trial-will-end';
import { Subscription } from '../store/models';
import { BaseSubscriptionScheduleNotification, BaseSubscriptionScheduleNotificationEventType } from './base';
import type { Diff, Task } from './interface/base';

export class SubscriptionTrialWillEndSchedule extends BaseSubscriptionScheduleNotification<SubscriptionTrialWillEndEmailTemplateOptions> {
  override eventType: BaseSubscriptionScheduleNotificationEventType = 'customer.subscription.trial_will_end';

  async getSubscriptions(): Promise<Subscription[]> {
    const subscriptions = await Subscription.findAll({
      where: {
        // @note: 之所以除 1000,是因为时间的精确度是 s
        current_period_start: {
          [Op.lte]: this.start / 1000,
        },
        trial_end: {
          [Op.lt]: this.end / 1000,
        },
        trial_start: {
          [Op.gt]: 0,
        },
        status: 'trialing',
      },
      attributes: ['id', 'current_period_start', 'current_period_end', 'trial_end', 'status'],
      raw: true,
    });

    return subscriptions;
  }

  override getTask({
    subscription,
    diff,
  }: {
    subscription: Subscription;
    diff: Diff;
  }): Task<SubscriptionTrialWillEndEmailTemplateOptions> {
    const type = this.eventType;
    if (subscription.status !== 'trialing') {
      throw new Error(`Subscription(${subscription.id}) is not trialing, no need to send notification`);
    }

    const trialEnd = this.getEndTime(subscription);
    if (!subscription.trial_end) {
      throw new Error(`Subscription(${subscription.id}) has no trial_end, no need to send notification`);
    }

    if (trialEnd <= this.start) {
      throw new Error(`Subscription(${subscription.id}) is already expired, no need to send notification`);
    }

    return {
      id: `${subscription.id}.${type}.${diff.value}.${diff.unit}`,
      job: {
        type,
        options: {
          subscriptionId: subscription.id,
          willRenewValue: diff.value,
          willRenewUnit: diff.unit,
          required: !!diff.required,
        },
      },
      delay: dayjs(trialEnd).subtract(diff.value, diff.unit).diff(this.start, 's'),
    };
  }

  override getEndTime(subscription: Subscription): number {
    return subscription.trial_end! * 1000;
  }
}
