/* eslint-disable @typescript-eslint/brace-style */
/* eslint-disable @typescript-eslint/indent */
import type { ManipulateType } from 'dayjs';

import dayjs from '../../dayjs';
import { translate } from '../../../locales';
import { Invoice, PaymentCurrency, PaymentMethod } from '../../../store/models';
import { formatTime, getSimplifyDuration } from '../../time';
import { formatTokenAmount } from '../../util';
import { BaseSubscriptionEmailTemplate, BaseEmailTemplateType } from './base';

export interface SubscriptionWillCanceledEmailTemplateOptions {
  subscriptionId: string;
  willCancelValue: number;
  willCancelUnit: ManipulateType;
  required?: false | true;
}

interface SubscriptionWillCanceledEmailTemplateContext {
  locale: string;
  productName: string;
  at: string;
  cancelReason: string;
  body: string;
  userDid: string;
  paymentInfo: string;
  viewSubscriptionLink: string;
  viewInvoiceLink?: string;
  customActions: any[];
  needRenew: boolean;
  isCreditSubscription: boolean;
}

export class SubscriptionWillCanceledEmailTemplate extends BaseSubscriptionEmailTemplate<SubscriptionWillCanceledEmailTemplateContext> {
  options: SubscriptionWillCanceledEmailTemplateOptions;

  constructor(options: SubscriptionWillCanceledEmailTemplateOptions) {
    super();
    this.options = options;
  }

  async getContext(): Promise<SubscriptionWillCanceledEmailTemplateContext> {
    if (!this.options.required) {
      throw new Error('SubscriptionWillCanceledEmailTemplate: This execution will be skipped');
    }

    // 获取基础订阅数据
    const basicData = await this.getSubscriptionBasicData(this.options.subscriptionId);
    const { subscription, userDid, locale, productName, isCreditSubscription } = basicData;

    if (subscription.isImmutable()) {
      throw new Error(`Subscription(${this.options.subscriptionId}) is immutable, no need to send notification`);
    }

    const now = dayjs().unix();
    const cancelAt = subscription.cancel_at || subscription.current_period_end;
    if (!subscription.cancel_at && !subscription.cancel_at_period_end) {
      throw new Error(
        `Subscription(${this.options.subscriptionId}) is not scheduled to cancel, no need to send notification`
      );
    }
    if (cancelAt <= now) {
      throw new Error(`Subscription(${this.options.subscriptionId}) is already canceled, no need to send notification`);
    }

    // 获取发票和支付信息
    const invoice = await Invoice.findOne({
      where: { id: subscription.latest_invoice_id },
      include: [
        { model: PaymentCurrency, as: 'paymentCurrency' },
        { model: PaymentMethod, as: 'paymentMethod' },
      ],
    });
    if (!invoice) {
      throw new Error(`Invoice(${subscription.latest_invoice_id}) not found`);
    }

    // 获取链接
    const links = this.generateSubscriptionLinks(
      subscription,
      locale,
      userDid,
      'customer.subscription.will_canceled',
      subscription.latest_invoice_id,
      isCreditSubscription
    );

    // 计算时间和取消原因
    const at = formatTime(cancelAt * 1000);
    const willCancelDuration = getSimplifyDuration((cancelAt - now) * 1000, locale);

    // @ts-ignore
    const paymentInfo = `${formatTokenAmount(invoice.total, invoice?.paymentCurrency?.decimal)} ${invoice?.paymentCurrency?.symbol}${invoice?.paymentMethod ? `(${invoice?.paymentMethod.name})` : ''}`;

    let body = translate('notification.subscriptWillCanceled.body', locale, {
      productName,
      willCancelDuration,
      at,
    });

    let needRenew = false;
    const reasonMap = {
      cancellation_requested: 'customerCanceled',
      payment_failed: 'paymentFailed',
      stake_revoked: 'stakeRevoked',
    } as const;

    const cancelReason = translate(
      `notification.subscriptWillCanceled.${reasonMap[subscription.cancelation_details?.reason as keyof typeof reasonMap] || 'adminCanceled'}`,
      locale,
      {
        canceled_at: formatTime(subscription.canceled_at ? subscription.canceled_at * 1000 : dayjs().unix()),
      }
    );

    if (subscription.status === 'past_due' || subscription.cancelation_details?.reason === 'payment_failed') {
      body = translate('notification.subscriptWillCanceled.pastDue', locale, {
        productName,
        willCancelDuration,
        at,
      });
      needRenew = true;
    }

    return {
      locale,
      productName,
      at,
      body,
      cancelReason,
      userDid,
      paymentInfo,
      viewSubscriptionLink: links.viewSubscriptionLink,
      viewInvoiceLink: links.viewInvoiceLink,
      customActions: links.customActions,
      needRenew,
      isCreditSubscription,
    };
  }

  async getTemplate(): Promise<BaseEmailTemplateType | null> {
    const context = await this.getContext();
    const {
      locale,
      productName,
      at,
      body,
      cancelReason,
      needRenew,
      userDid,
      paymentInfo,
      viewSubscriptionLink,
      viewInvoiceLink,
      customActions,
      isCreditSubscription,
    } = context;

    // 如果当前时间大于订阅终止时间，那么不发送通知
    if (dayjs().utc().isAfter(dayjs.utc(at))) {
      return null;
    }

    // 构建字段
    const commonFields = this.buildCommonFields(userDid, productName, locale);

    // 支付金额字段（仅在需要续费时显示）
    const paymentAmountFields =
      needRenew && !isCreditSubscription
        ? [
            {
              type: 'text',
              data: {
                type: 'plain',
                color: '#9397A1',
                text: translate('notification.common.paymentAmount', locale),
              },
            },
            {
              type: 'text',
              data: {
                type: 'plain',
                text: paymentInfo,
              },
            },
          ]
        : [];

    // 取消原因字段
    const cancelReasonFields = [
      {
        type: 'text',
        data: {
          type: 'plain',
          color: '#9397A1',
          text: translate('notification.subscriptWillCanceled.cancelReason', locale),
        },
      },
      {
        type: 'text',
        data: {
          type: 'plain',
          text: cancelReason,
        },
      },
    ];

    // 构建操作按钮
    const actions = [
      viewSubscriptionLink && {
        name: translate('notification.common.viewSubscription', locale),
        title: translate('notification.common.viewSubscription', locale),
        link: viewSubscriptionLink,
      },
      viewInvoiceLink &&
        needRenew && {
          name: translate('notification.common.renewNow', locale),
          title: translate('notification.common.renewNow', locale),
          link: viewInvoiceLink,
        },
      ...customActions,
    ].filter(Boolean);

    const template: BaseEmailTemplateType = {
      title: translate('notification.subscriptWillCanceled.title', locale, {
        productName,
      }),
      body,
      // @ts-expect-error
      attachments: [
        {
          type: 'section',
          fields: [...commonFields, ...paymentAmountFields, ...cancelReasonFields].filter(Boolean),
        },
      ].filter(Boolean),
      // @ts-ignore
      actions,
    };

    return template;
  }
}
