import { fromTokenToUnit } from '@ocap/util';
import Sequelize from 'sequelize';
import { joinURL } from 'ufo';

import { createIdGenerator } from '../../libs/util';
import type { Migration } from '../migrate';

const getUrl = (...parts: string[]): string => {
  const { BLOCKLET_COMPONENT_DID, BLOCKLET_APP_URL } = process.env;
  const components = JSON.parse(process.env.BLOCKLET_MOUNT_POINTS || '[]');
  const component = components.find((x: any) => [x.title, x.name, x.did].includes(BLOCKLET_COMPONENT_DID));
  const mountPoint = component?.mountPoint || '/';
  return joinURL(BLOCKLET_APP_URL as string, mountPoint === '/' ? '' : mountPoint, ...parts);
};

export const up: Migration = async ({ context }) => {
  const genPaymentMethodId = createIdGenerator('pm', 24);
  const genPaymentCurrencyId = createIdGenerator('pc', 12);

  const abtId = genPaymentCurrencyId();
  const tbaId = genPaymentCurrencyId();
  const marsId = genPaymentCurrencyId();
  const play3Id = genPaymentCurrencyId();
  const mainId = genPaymentMethodId();
  const betaId = genPaymentMethodId();
  const now = new Date();

  const logo = getUrl('/methods/arcblock.png');

  const paymentCurrencies = [
    {
      id: abtId,
      active: true,
      livemode: true,
      locked: true,
      is_base_currency: true,
      payment_method_id: mainId,
      name: 'Native ABT',
      description: 'ABT on ArcBlock main chain',
      logo,
      symbol: 'ABT',
      decimal: 18,
      minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
      maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
      contract: 'z35nNRvYxBoHitx9yZ5ATS88psfShzPPBLxYD',
      metadata: {},
      created_at: now,
      updated_at: now,
    },
    {
      id: tbaId,
      active: true,
      livemode: false,
      locked: true,
      is_base_currency: true,
      payment_method_id: betaId,
      name: 'Test ABT',
      description: 'ABT on ArcBlock beta chain',
      logo,
      symbol: 'TBA',
      decimal: 18,
      minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
      maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
      contract: 'z35n6UoHSi9MED4uaQy6ozFgKPaZj2UKrurBG',
      metadata: {},
      created_at: now,
      updated_at: now,
    },
    {
      id: marsId,
      active: true,
      livemode: false,
      locked: false,
      is_base_currency: false,
      payment_method_id: betaId,
      name: 'RollupTestToken',
      description: 'Token to test rollup on staging',
      logo,
      symbol: 'MARS',
      decimal: 18,
      minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
      maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
      contract: 'z35n4nCsnAEWa2zVSKNKZhDGXSszaJAogSc3A',
      metadata: {},
      created_at: now,
      updated_at: now,
    },
    {
      id: play3Id,
      active: true,
      livemode: false,
      locked: false,
      is_base_currency: false,
      payment_method_id: betaId,
      name: 'Playground Token',
      description: 'Test Token for OCAP Playground',
      logo,
      symbol: 'PLAY3',
      decimal: 18,
      minimum_payment_amount: fromTokenToUnit(0.1, 18).toString(), // 0.1 token
      maximum_payment_amount: fromTokenToUnit(100000000, 18).toString(), // 0.1 billion
      contract: 'z35n3WVTnN7KrR4gXn3szR6oneVefkBBx78Fc',
      metadata: {},
      created_at: now,
      updated_at: now,
    },
  ];

  const paymentMethods = [
    {
      id: mainId,
      active: true,
      livemode: true,
      locked: true,
      type: 'arcblock',
      name: 'ArcBlock Main',
      description: 'Process payments with tokens on ArcBlock main chain',
      logo,
      default_currency_id: abtId,
      confirmation: {
        type: 'immediate',
      },
      settings: {
        arcblock: {
          chain_id: 'main',
          api_host: 'https://main.abtnetwork.io/api/',
          explorer_host: 'https://main.abtnetwork.io/explorer/',
        },
      },
      features: {
        recurring: true,
        refund: true,
        dispute: false,
      },
      metadata: {},
      created_at: now,
      updated_at: now,
    },
    {
      id: betaId,
      active: true,
      livemode: false,
      locked: true,
      type: 'arcblock',
      name: 'ArcBlock Beta',
      description: 'Process payments with tokens on ArcBlock beta chain, just for test purpose',
      logo,
      default_currency_id: tbaId,
      confirmation: {
        type: 'immediate',
      },
      settings: {
        arcblock: {
          chain_id: 'beta',
          api_host: 'https://beta.abtnetwork.io/api/',
          explorer_host: 'https://beta.abtnetwork.io/explorer/',
        },
      },
      features: {
        recurring: true,
        refund: true,
        dispute: false,
      },
      metadata: {},
      created_at: now,
      updated_at: now,
    },
  ];

  await context.bulkInsert(
    'payment_methods',
    paymentMethods,
    {},
    {
      confirmation: { type: new Sequelize.JSON() },
      settings: { type: new Sequelize.JSON() },
      features: { type: new Sequelize.JSON() },
      metadata: { type: new Sequelize.JSON() },
    }
  );
  await context.bulkInsert(
    'payment_currencies',
    paymentCurrencies,
    {},
    {
      metadata: { type: new Sequelize.JSON() },
    }
  );
};

export const down: Migration = async ({ context }) => {
  await context.bulkDelete('payment_methods', {});
  await context.bulkDelete('payment_currencies', {});
};
