/* eslint-disable @typescript-eslint/brace-style */
/* eslint-disable @typescript-eslint/indent */
import { translate } from '../../../locales';
import { PaymentIntent, PaymentMethod, Refund, Customer, CheckoutSession } from '../../../store/models';
import { Invoice } from '../../../store/models/invoice';
import { PaymentCurrency } from '../../../store/models/payment-currency';
import { getUserLocale } from '../../../integrations/blocklet/notification';
import { getMainProductNameByCheckoutSession } from '../../product';
import { formatTime } from '../../time';
import { formatCurrencyInfo, getExplorerLink } from '../../util';
import type { BaseEmailTemplate, BaseEmailTemplateType } from './base';
import { getCustomerInvoicePageUrl } from '../../invoice';

export interface OneTimePaymentRefundSucceededEmailTemplateOptions {
  refundId: string;
}

interface OneTimePaymentRefundSucceededEmailTemplateContext {
  locale: string;
  productName: string | undefined;
  at: string;
  chainHost: string | undefined;
  userDid: string;
  paymentInfo: string;
  refundInfo: string;
  viewInvoiceLink: string;
  viewTxHashLink: string | undefined;
  refund: Refund;
  invoiceNumber?: string;
}

export class OneTimePaymentRefundSucceededEmailTemplate
  implements BaseEmailTemplate<OneTimePaymentRefundSucceededEmailTemplateContext>
{
  options: OneTimePaymentRefundSucceededEmailTemplateOptions;

  constructor(options: OneTimePaymentRefundSucceededEmailTemplateOptions) {
    this.options = options;
  }

  async getContext(): Promise<OneTimePaymentRefundSucceededEmailTemplateContext> {
    const refund = await Refund.findByPk(this.options.refundId);
    if (!refund) {
      throw new Error(`Refund not found: ${this.options.refundId}`);
    }
    if (refund.status !== 'succeeded') {
      throw new Error(`Refund not succeeded: ${this.options.refundId}`);
    }

    const customer = await Customer.findByPk(refund.customer_id);
    if (!customer) {
      throw new Error(`Customer not found: ${refund.customer_id}`);
    }
    const userDid = customer.did;
    const locale = await getUserLocale(userDid);

    let invoiceNumber: string | undefined;
    let productName: string | undefined;
    let viewInvoiceLink = '';

    if (refund.invoice_id) {
      const invoice = await Invoice.findByPk(refund.invoice_id);
      if (invoice) {
        invoiceNumber = invoice.number;
        viewInvoiceLink = getCustomerInvoicePageUrl({
          invoiceId: refund.invoice_id,
          userDid,
          locale,
        });

        if (invoice.checkout_session_id) {
          const checkoutSession = await CheckoutSession.findByPk(invoice.checkout_session_id);
          if (checkoutSession) {
            productName = await getMainProductNameByCheckoutSession(checkoutSession);
          }
        }
      }
    }

    const paymentIntent = await PaymentIntent.findByPk(refund.payment_intent_id);
    const paymentCurrency = await PaymentCurrency.findByPk(refund.currency_id);
    if (!paymentCurrency) {
      throw new Error(`PaymentCurrency not found: ${refund.currency_id}`);
    }

    const paymentMethod = await PaymentMethod.findByPk(refund.payment_method_id);

    const paymentInfo = formatCurrencyInfo(paymentIntent?.amount_received || '0', paymentCurrency, paymentMethod);
    const refundInfo = formatCurrencyInfo(refund.amount, paymentCurrency, paymentMethod);

    // @ts-expect-error
    const chainHost = paymentMethod?.settings?.[paymentMethod?.type]?.api_host;
    // @ts-expect-error
    const txHash = refund?.payment_details?.[paymentMethod?.type]?.tx_hash;
    const viewTxHashLink =
      txHash &&
      getExplorerLink({
        type: 'tx',
        did: txHash,
        chainHost,
      });

    const at = formatTime(refund.created_at);

    return {
      locale,
      productName,
      at,
      userDid,
      chainHost,
      paymentInfo,
      refundInfo,
      viewInvoiceLink,
      viewTxHashLink,
      refund,
      invoiceNumber,
    };
  }

  async getTemplate(): Promise<BaseEmailTemplateType> {
    const {
      locale,
      productName,
      at,
      userDid,
      paymentInfo,
      refundInfo,
      viewInvoiceLink,
      viewTxHashLink,
      refund,
      invoiceNumber,
    } = await this.getContext();

    if (refund.type === 'stake_return') {
      throw new Error('Stake return is not supported for one-time payment refunds');
    }

    const commonFields = [
      {
        type: 'text',
        data: {
          type: 'plain',
          color: '#9397A1',
          text: translate('notification.common.account', locale),
        },
      },
      {
        type: 'text',
        data: {
          type: 'plain',
          text: userDid,
        },
      },
    ];

    const productFields = productName
      ? [
          {
            type: 'text',
            data: {
              type: 'plain',
              color: '#9397A1',
              text: translate('notification.common.product', locale),
            },
          },
          {
            type: 'text',
            data: {
              type: 'plain',
              text: productName,
            },
          },
        ]
      : [];

    const amountFields = [
      {
        type: 'text',
        data: {
          type: 'plain',
          color: '#9397A1',
          text: translate('notification.common.paymentAmount', locale),
        },
      },
      {
        type: 'text',
        data: {
          type: 'plain',
          text: paymentInfo,
        },
      },
      {
        type: 'text',
        data: {
          type: 'plain',
          color: '#9397A1',
          text: translate('notification.common.refundAmount', locale),
        },
      },
      {
        type: 'text',
        data: {
          type: 'plain',
          text: refundInfo,
        },
      },
    ];

    const invoiceFields = invoiceNumber
      ? [
          {
            type: 'text',
            data: {
              type: 'plain',
              color: '#9397A1',
              text: translate('notification.common.invoiceNumber', locale),
            },
          },
          {
            type: 'text',
            data: {
              type: 'plain',
              text: invoiceNumber,
            },
          },
        ]
      : [];

    const actions = [
      viewInvoiceLink && {
        name: translate('notification.common.viewInvoice', locale),
        title: translate('notification.common.viewInvoice', locale),
        link: viewInvoiceLink,
      },
      viewTxHashLink && {
        name: translate('notification.common.viewTxHash', locale),
        title: translate('notification.common.viewTxHash', locale),
        link: viewTxHashLink,
      },
    ].filter(Boolean);

    const titleKey = productName
      ? 'notification.oneTimePaymentRefundSucceeded.title'
      : 'notification.oneTimePaymentRefundSucceeded.titleNoProduct';

    const bodyKey = productName
      ? 'notification.oneTimePaymentRefundSucceeded.body'
      : 'notification.oneTimePaymentRefundSucceeded.bodyNoProduct';

    const template: BaseEmailTemplateType = {
      title: translate(titleKey, locale, {
        productName,
        invoiceNumber: invoiceNumber || '',
      }),
      body: translate(bodyKey, locale, {
        at,
        productName,
        refundInfo,
        invoiceNumber: invoiceNumber || '',
      }),
      // @ts-expect-error
      attachments: [
        {
          type: 'section',
          fields: [...commonFields, ...productFields, ...amountFields, ...invoiceFields].filter(Boolean),
        },
      ].filter(Boolean),
      // @ts-ignore
      actions,
    };

    return template;
  }
}
