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

import { getTokenByAddress } from '../../../integrations/arcblock/stake';
import { translate } from '../../../locales';
import { PaymentDetail } from '../../payment';
import { getPaymentAmountForCycleSubscription } from '../../subscription';
import { formatTime, getSimplifyDuration } from '../../time';
import dayjs from '../../dayjs';
import { BaseSubscriptionEmailTemplate, BaseEmailTemplateType } from './base';

export interface SubscriptionTrialWillEndEmailTemplateOptions {
  subscriptionId: string;
  willRenewValue: number;
  willRenewUnit: ManipulateType;
  required?: false | true;
}

interface SubscriptionTrialWillEndEmailTemplateContext {
  locale: string;
  productName: string;
  at: string;
  willEndDuration: string;
  paymentDetail: PaymentDetail;
  userDid: string;
  paymentInfo: string;
  currentPeriodStart: string;
  currentPeriodEnd: string;
  duration: string;
  viewSubscriptionLink: string;
  customActions: any[];
  isCreditSubscription: boolean;
  isStripe: boolean;
}

export class SubscriptionTrialWillEndEmailTemplate extends BaseSubscriptionEmailTemplate<SubscriptionTrialWillEndEmailTemplateContext> {
  options: SubscriptionTrialWillEndEmailTemplateOptions;

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

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

    if (subscription.status !== 'trialing') {
      throw new Error(`Subscription not trialing: ${this.options.subscriptionId}`);
    }
    if (subscription.isScheduledToCancel()) {
      throw new Error(`Subscription is scheduled to cancel: ${this.options.subscriptionId}`);
    }

    if (!subscription.trial_end) {
      throw new Error(`Subscription has no trial end: ${subscription.id}`);
    }

    // 获取支付信息
    const paymentInfoResult = await this.getPaymentInfo(subscription, paymentCurrency, isCreditSubscription);
    const { paymentMethod } = paymentInfoResult;

    if (!paymentMethod) {
      throw new Error(`Payment method not found: ${paymentCurrency.payment_method_id}`);
    }

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

    // 计算时间信息
    const at = formatTime((subscription.trial_end as number) * 1000);
    const willEndDuration = getSimplifyDuration((subscription.trial_end! - dayjs().unix()) * 1000, locale);

    // 获取支付详情
    const paymentAmount = await getPaymentAmountForCycleSubscription(subscription, paymentCurrency);
    const paymentDetail = { price: paymentAmount, balance: 0, symbol: paymentCurrency.symbol };

    // 获取余额信息（非 Stripe 支付方式）
    const isStripe = paymentMethod?.type === 'stripe';
    if (!isStripe && !isCreditSubscription) {
      // @ts-ignore
      const paymentAddress = subscription.payment_details?.[paymentMethod.type]?.payer ?? undefined;
      const balance = await getTokenByAddress(paymentAddress, paymentMethod, paymentCurrency);

      // @ts-ignore
      paymentDetail.balance = +fromUnitToToken(balance, paymentCurrency.decimal);
    }

    const paymentInfo = `${paymentAmount} ${paymentCurrency.symbol}`;

    // 计算周期信息
    const periodInfo = this.formatSubscriptionPeriod(
      subscription.trial_start as number,
      subscription.trial_end as number,
      locale
    );

    return {
      locale,
      productName,
      at,
      willEndDuration,
      paymentDetail,
      userDid,
      paymentInfo,
      currentPeriodStart: periodInfo.currentPeriodStart,
      currentPeriodEnd: periodInfo.currentPeriodEnd,
      duration: periodInfo.duration,
      viewSubscriptionLink: links.viewSubscriptionLink,
      customActions: links.customActions,
      isCreditSubscription,
      isStripe,
    };
  }

  async getTemplate(): Promise<BaseEmailTemplateType | null> {
    const context = await this.getContext();
    const {
      locale,
      productName,
      at,
      willEndDuration,
      paymentDetail,
      userDid,
      paymentInfo,
      currentPeriodStart,
      currentPeriodEnd,
      duration,
      viewSubscriptionLink,
      customActions,
      isCreditSubscription,
      isStripe,
    } = context;

    // 如果当前时间大于试用结束时间，那么不发送通知
    if (dayjs().utc().isAfter(dayjs.utc(at))) {
      return null;
    }

    const canPay = paymentDetail.balance >= paymentDetail.price;
    if (canPay && !this.options.required) {
      return null;
    }

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

    // 支付金额字段
    const paymentAmountFields = isCreditSubscription
      ? []
      : [
          {
            type: 'text',
            data: {
              type: 'plain',
              color: '#9397A1',
              text: translate('notification.common.paymentAmount', locale),
            },
          },
          {
            type: 'text',
            data: {
              type: 'plain',
              text: paymentInfo,
            },
          },
        ];

    // 余额不足提醒字段
    const insufficientBalanceFields =
      !canPay && !isStripe && !isCreditSubscription
        ? [
            {
              type: 'text',
              data: {
                type: 'plain',
                color: '#9397A1',
                text: translate('notification.common.balanceReminder', locale),
              },
            },
            {
              type: 'text',
              data: {
                type: 'plain',
                color: '#FF0000',
                text: translate('notification.subscriptionTrialWillEnd.unableToPayReason', locale, {
                  balance: `${paymentDetail.balance} ${paymentDetail.symbol}`,
                  price: `${paymentDetail.price} ${paymentDetail.symbol}`,
                }),
              },
            },
          ]
        : [];

    // 试用期字段
    const trialPeriodFields = isCreditSubscription
      ? []
      : [
          {
            type: 'text',
            data: {
              type: 'plain',
              color: '#9397A1',
              text: translate('notification.common.trialPeriod', locale),
            },
          },
          {
            type: 'text',
            data: {
              type: 'plain',
              text: `${currentPeriodStart} ~ ${currentPeriodEnd}(${duration})`,
            },
          },
        ];

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

    const template: BaseEmailTemplateType = {
      title: translate('notification.subscriptionTrialWillEnd.title', locale, {
        productName,
        willEndDuration,
      }),
      body:
        canPay || isStripe
          ? translate('notification.subscriptionTrialWillEnd.body', locale, {
              at,
              productName,
              willEndDuration,
            })
          : translate('notification.subscriptionTrialWillEnd.unableToPayBody', locale, {
              at,
              productName,
              willEndDuration,
              balance: `${paymentDetail.balance} ${paymentDetail.symbol}`,
              price: `${paymentDetail.price} ${paymentDetail.symbol}`,
            }),
      // @ts-expect-error
      attachments: [
        {
          type: 'section',
          fields: [...commonFields, ...paymentAmountFields, ...insufficientBalanceFields, ...trialPeriodFields].filter(
            Boolean
          ),
        },
      ].filter(Boolean),
      // @ts-ignore
      actions,
    };

    return template;
  }
}
