/* eslint-disable @typescript-eslint/brace-style */
/* eslint-disable @typescript-eslint/indent */
import { translate } from '../../../locales';
import { PaymentIntent, NftMintItem } from '../../../store/models';
import { Invoice } from '../../../store/models/invoice';
import { formatTime } from '../../time';
import { formatCurrencyInfo, getExplorerLink } from '../../util';
import { BaseSubscriptionEmailTemplate, BaseEmailTemplateType } from './base';

export interface SubscriptionUpgradedEmailTemplateOptions {
  subscriptionId: string;
}

interface SubscriptionUpgradedEmailTemplateContext {
  locale: string;
  productName: string;
  at: string;
  nftMintItem: NftMintItem | undefined;
  chainHost: string | undefined;
  userDid: string;
  paymentInfo: string;
  currentPeriodStart: string;
  currentPeriodEnd: string;
  duration: string;
  viewSubscriptionLink: string;
  viewInvoiceLink: string;
  viewTxHashLink: string | undefined;
  skipInvoice: boolean;
  customActions: any[];
  isCreditSubscription: boolean;
}

export class SubscriptionUpgradedEmailTemplate extends BaseSubscriptionEmailTemplate<SubscriptionUpgradedEmailTemplateContext> {
  options: SubscriptionUpgradedEmailTemplateOptions;

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

  async getContext(): Promise<SubscriptionUpgradedEmailTemplateContext> {
    // 获取基础订阅数据
    const basicData = await this.getSubscriptionBasicData(this.options.subscriptionId);
    const { subscription, userDid, locale, productName, paymentCurrency, isCreditSubscription } = basicData;

    if (!subscription.isActive()) {
      throw new Error(`Subscription not active: ${this.options.subscriptionId}`);
    }

    // invoice应该是最新的subscription_update invoice
    const invoiceId = subscription.pending_update?.updates?.latest_invoice_id || subscription.latest_invoice_id;
    const invoice = (await Invoice.findByPk(invoiceId)) as Invoice;
    const skipInvoice = subscription.status === 'trialing' || invoice.billing_reason !== 'subscription_update';
    const paymentIntent = await PaymentIntent.findByPk(invoice.payment_intent_id);

    // 获取支付信息
    const paymentInfoResult = await this.getPaymentInfo(
      subscription,
      paymentCurrency,
      isCreditSubscription,
      invoice?.id
    );

    // 获取链接
    const links = this.generateSubscriptionLinks(
      subscription,
      locale,
      userDid,
      'customer.subscription.upgraded',
      invoice?.id,
      isCreditSubscription
    );

    // 获取 NFT 信息
    const nftInfo = await this.getNftMintInfo(subscription.id);

    // 格式化支付信息
    const formattedPaymentInfo = formatCurrencyInfo(
      paymentIntent?.amount || invoice.amount_paid,
      paymentCurrency,
      paymentInfoResult.paymentMethod
    );

    // 格式化时间信息
    const periodInfo = this.formatSubscriptionPeriod(
      skipInvoice ? subscription.current_period_start : invoice.period_start,
      skipInvoice ? subscription.current_period_end : invoice.period_end,
      locale
    );

    // 获取交易哈希链接
    const txHash: string | undefined = (paymentIntent?.payment_details as any)?.[
      paymentInfoResult?.paymentMethod?.type as string
    ]?.tx_hash;
    const chainHost: string | undefined = (paymentInfoResult?.paymentMethod?.settings as any)?.[
      paymentInfoResult.paymentMethod?.type as string
    ]?.api_host;
    const viewTxHashLink: string | undefined = txHash && getExplorerLink({ type: 'tx', did: txHash, chainHost });

    return {
      locale,
      productName,
      at: formatTime(subscription.created_at),
      userDid,
      nftMintItem: nftInfo.nftMintItem,
      chainHost,
      paymentInfo: formattedPaymentInfo,
      currentPeriodStart: periodInfo.currentPeriodStart,
      currentPeriodEnd: periodInfo.currentPeriodEnd,
      duration: periodInfo.duration,
      viewSubscriptionLink: links.viewSubscriptionLink,
      viewInvoiceLink: links.viewInvoiceLink!,
      viewTxHashLink,
      skipInvoice,
      customActions: links.customActions,
      isCreditSubscription,
    };
  }

  async getTemplate(): Promise<BaseEmailTemplateType> {
    const context = await this.getContext();
    const {
      locale,
      productName,
      at,
      nftMintItem,
      chainHost,
      userDid,
      paymentInfo,
      currentPeriodStart,
      currentPeriodEnd,
      duration,
      viewSubscriptionLink,
      viewInvoiceLink,
      viewTxHashLink,
      skipInvoice,
      customActions,
      isCreditSubscription,
    } = context;

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

    // 构建支付金额字段（跳过发票时不显示）
    const paymentFields = skipInvoice || isCreditSubscription ? [] : this.buildPaymentField(paymentInfo, locale, false);

    // 构建有效期字段
    const periodFields = this.buildPeriodField(
      currentPeriodStart,
      currentPeriodEnd,
      duration,
      locale,
      isCreditSubscription
    );

    // 构建操作按钮
    const baseActions = this.buildCommonActions(
      viewSubscriptionLink,
      skipInvoice ? undefined : viewInvoiceLink,
      locale,
      isCreditSubscription,
      []
    );

    const additionalActions = [
      !skipInvoice &&
        viewTxHashLink && {
          name: translate('notification.common.viewTxHash', locale),
          title: translate('notification.common.viewTxHash', locale),
          link: viewTxHashLink,
        },
      ...customActions,
    ];

    const template: BaseEmailTemplateType = {
      title: translate('notification.subscriptionUpgraded.title', locale, { productName }),
      body: translate('notification.subscriptionUpgraded.body', locale, { at, productName }),
      // @ts-expect-error
      attachments: [
        nftMintItem &&
          chainHost && {
            type: 'asset',
            data: { chainHost, did: nftMintItem.address },
          },
        {
          type: 'section',
          fields: [...commonFields, ...paymentFields, ...periodFields].filter(Boolean),
        },
      ].filter(Boolean),
      // @ts-ignore
      actions: [...baseActions, ...additionalActions].filter(Boolean),
    };

    return template;
  }
}
