/* eslint-disable @typescript-eslint/brace-style */
/* eslint-disable @typescript-eslint/indent */
import { getUrl } from '@blocklet/sdk';
import { getUserLocale } from '../../../integrations/blocklet/notification';
import { translate } from '../../../locales';
import { CheckoutSession, Customer, PaymentLink, PaymentMethod, Payout } from '../../../store/models';
import { PaymentCurrency } from '../../../store/models/payment-currency';
import { formatTime } from '../../time';
import { formatTokenAmount, getCustomerProfileUrl, getExplorerLink, getUserOrAppInfo } from '../../util';
import type { BaseEmailTemplate, BaseEmailTemplateType } from './base';
import { getCustomerPayoutPageUrl } from '../../payout';
import { PaymentIntent } from '../../../store/models/payment-intent';

export interface CustomerRevenueSucceededEmailTemplateOptions {
  payoutId: string;
}

interface CustomerRevenueSucceededEmailTemplateContext {
  locale: string;
  at: string;
  paymentIntentId: string;

  chainHost: string | undefined;
  userDid: string;
  paymentInfo: string;
  user: string;
  revenueDetail: {
    url: string;
    title: string;
    appDID: string;
    logo?: string;
    desc?: string;
  };

  viewPayoutLink: string;
  viewTxHashLink: string;
  type: 'payment' | 'donate';
}

/**
 * @description
 * @export
 * @class CustomerRevenueSucceededEmailTemplate
 * @implements {BaseEmailTemplate<CustomerRevenueSucceededEmailTemplateContext>}
 */
export class CustomerRevenueSucceededEmailTemplate
  implements BaseEmailTemplate<CustomerRevenueSucceededEmailTemplateContext>
{
  options: CustomerRevenueSucceededEmailTemplateOptions;

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

  async getContext(): Promise<CustomerRevenueSucceededEmailTemplateContext> {
    const payout = (await Payout.findByPk(this.options.payoutId, {
      include: [
        {
          model: PaymentIntent,
          as: 'paymentIntent',
        },
      ],
    })) as Payout & { paymentIntent: PaymentIntent };
    if (!payout) {
      throw new Error(`Payout(${this.options.payoutId}) not found`);
    }

    if (!payout.paymentIntent) {
      throw new Error(`PaymentIntent not found for payout: ${this.options.payoutId}`);
    }

    const customer = await Customer.findByPk(payout.customer_id);
    if (!customer) {
      throw new Error(`Customer not found: ${payout.customer_id}`);
    }

    const paymentCurrency = (await PaymentCurrency.findOne({
      where: {
        id: payout.currency_id,
      },
    })) as PaymentCurrency;

    const userDid: string = customer.did;
    const locale = await getUserLocale(userDid);
    const at: string = formatTime(payout.created_at);
    let type: 'payment' | 'donate' = 'payment';

    try {
      const checkoutSession = await CheckoutSession.findOne({
        where: {
          payment_intent_id: payout.payment_intent_id,
        },
        attributes: ['id', 'submit_type'],
      });
      if (checkoutSession && checkoutSession.submit_type === 'donate') {
        type = 'donate';
      }
    } catch (error) {
      console.error(error);
    }

    const payer = await Customer.findByPk(payout.paymentIntent?.customer_id);
    if (!payer) {
      throw new Error(`Payer not found for paymentIntent: ${payout.paymentIntent?.customer_id}`);
    }

    const paymentInfo: string = `${formatTokenAmount(payout.amount, paymentCurrency.decimal)} ${paymentCurrency.symbol}`;
    const userInfo = await getUserOrAppInfo(payer.did);
    const revenueDetail = {
      url: getCustomerProfileUrl({ userDid: payer.did, locale }),
      title: translate('notification.customerRevenueSucceeded.sended', locale, {
        address: payer.name || payer.did,
        amount: paymentInfo,
      }),
      logo: userInfo?.avatar || getUrl('/methods/default.png'),
      appDID: payer.did,
      desc: '',
    };

    const paymentMethod: PaymentMethod | null = await PaymentMethod.findByPk(payout.payment_method_id);
    // @ts-expect-error
    const chainHost: string | undefined = paymentMethod?.settings?.[paymentMethod.type]?.api_host;
    const viewPayoutLink = getCustomerPayoutPageUrl({
      payoutId: this.options.payoutId,
      userDid,
      locale,
    });

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

    return {
      locale,
      at,
      type,
      user: payer.name || userInfo?.name || payer.did,
      paymentIntentId: payout.payment_intent_id,
      userDid,
      chainHost,
      paymentInfo,
      revenueDetail,

      viewPayoutLink,
      viewTxHashLink,
    };
  }

  async getReference(paymentIntentId: string): Promise<string> {
    try {
      const checkoutSession = (await CheckoutSession.findOne({
        where: {
          payment_intent_id: paymentIntentId,
        },
        attributes: ['id', 'payment_link_id'],
      })) as CheckoutSession;
      if (!checkoutSession) {
        throw new Error(`CheckoutSession not found for paymentIntentId: ${paymentIntentId}`);
      }
      if (!checkoutSession.payment_link_id) {
        throw new Error(`Payment link cannot be found for checkoutSession: ${checkoutSession.id}`);
      }
      const paymentLink = await PaymentLink.findByPk(checkoutSession.payment_link_id);
      if (!paymentLink) {
        throw new Error(`Payment link cannot be found for payment_link_id(${checkoutSession.payment_link_id})`);
      }
      return paymentLink.donation_settings?.reference || '';
    } catch (error) {
      console.error(error);
      return '';
    }
  }

  async getTemplate(): Promise<BaseEmailTemplateType> {
    const {
      locale,
      at,
      user,
      type,
      paymentIntentId,
      paymentInfo,
      revenueDetail,

      viewPayoutLink,
      viewTxHashLink,
    } = await this.getContext();

    const reference = await this.getReference(paymentIntentId);

    const template: BaseEmailTemplateType = {
      title: translate(`notification.customerRevenueSucceeded.${type}.title`, locale),
      body: translate(`notification.customerRevenueSucceeded.${type}.body`, locale, {
        at,
        amount: paymentInfo,
        user,
      }),
      // @ts-expect-error
      attachments: [
        {
          type: 'section',
          fields: [
            {
              type: 'text',
              data: {
                type: 'plain',
                color: '#9397A1',
                text: translate('notification.customerRevenueSucceeded.sender', locale),
              },
            },
            {
              type: 'text',
              data: {
                type: 'plain',
                text: ' ',
              },
            },
          ].filter(Boolean),
        },
        {
          type: 'dapp',
          data: revenueDetail,
        },
      ].filter(Boolean),
      // @ts-expect-error
      actions: [
        viewPayoutLink && {
          name: translate('notification.customerRevenueSucceeded.viewDetail', locale),
          title: translate('notification.customerRevenueSucceeded.viewDetail', locale),
          link: viewPayoutLink,
        },
        viewTxHashLink && {
          name: translate('notification.common.viewTxHash', locale),
          title: translate('notification.common.viewTxHash', locale),
          link: viewTxHashLink,
        },
        reference && {
          name: translate('notification.customerRevenueSucceeded.donate.tipDetail', locale),
          title: translate('notification.customerRevenueSucceeded.donate.tipDetail', locale),
          link: reference,
        },
      ].filter(Boolean),
    };

    return template;
  }
}
