import { beforeEach, describe, expect, test } from 'vitest';
import { IndigoTestContext, repeat, runAndAwaitTx } from '../test-helpers';
import { expectScriptFailure } from '../utils/asserts';
import {
  createIndigoTestContext,
  EXAMPLE_TOKEN_1,
  EXAMPLE_TOKEN_2,
  EXAMPLE_TOKEN_3,
} from '../indigo-test-helpers';
import {
  findAdminInterestCollectors as findAdminInterestCollector,
  findAdminInterestCollectors,
  findAllInterestCollectors,
  findRandomNonAdminInterestCollector,
} from './interest-collector-queries';
import { benchmarkAndAwaitTx } from '../utils/benchmark-utils';
import {
  batchCollectInterest,
  distributeInterest,
  updatePermissions,
} from '../../src/contracts/interest-collection/transactions';
import {
  adaAssetClass,
  assetClassValueOf,
  matchSingle,
  mkAssetsOf,
  mkLovelacesOf,
} from '@3rd-eye-labs/cardano-offchain-common';
import {
  addAssets,
  fromHex,
  paymentCredentialOf,
  stakeCredentialOf,
} from '@lucid-evolution/lucid';
import {
  testCollectInterest,
  testDistributeInterest,
} from './transactions-mutated';
import { signersAllOf, fromSystemParamsAsset } from '../../src';
import {
  findAllActiveCdps,
  findAllNecessaryOrefs,
  findPriceOracleFromCollateralAsset,
} from '../cdp/cdp-queries';
import { feedPriceOracleTx } from '../../src/contracts/price-oracle/transactions';
import { createUtxosAtInterestCollector } from '../endpoints/interest-collector';
import { runOpenCdp } from '../cdp/actions';
import { runFeedPriceToOracle } from '../price-oracle/actions';
import { runTestDepositCdpWithInterestVar } from '../cdp/transactions-mutated';
import { findGov } from '../gov/governance-queries';
import { toDataMultisig } from '../../src/types/multisig';
import { createMultipleUtxosAtTreasury } from '../endpoints/treasury';
import { rationalFromInt } from '../../src/types/rational';

describe('Interest Collection', () => {
  beforeEach<IndigoTestContext>(async (context: IndigoTestContext) => {
    await createIndigoTestContext(context);
  });

  test<IndigoTestContext>('Collect Interest - Cannot collect without interacting with a CDP', async (context: IndigoTestContext) => {
    const interestCollectionUtxo = await findRandomNonAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    await expectScriptFailure(
      'Single CDP input in the transaction.',
      testCollectInterest(
        mkLovelacesOf(1000000n),
        context.lucid,
        context.systemParams,
        context.lucid.newTx(),
        interestCollectionUtxo,
        { kind: 'CollectWithoutCDP' },
      ),
    );
  });

  test<IndigoTestContext>('Collect Interest - Cannot collect from interest admin', async (context: IndigoTestContext) => {
    const adminInterestCollectorUtxo = await findAdminInterestCollectors(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const [iAssetConfig] = context.assetConfigs;

    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await runAndAwaitTx(
      context.lucid,
      runOpenCdp(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        10_000_000n,
        500_000n,
      ),
    );

    context.emulator.awaitSlot(6500);

    await runFeedPriceToOracle(
      context,
      context.systemParams,
      iAssetConfig,
      adaAssetClass,
      rationalFromInt(1n),
    );

    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await expectScriptFailure(
      'Spent UTxO cannot have admin NFT',
      runTestDepositCdpWithInterestVar(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        adminInterestCollectorUtxo,
        {
          kind: 'CollectFromInterestAdmin',
        },
      ),
    );
  });

  test<IndigoTestContext>('Collect Interest - Cannot collect from multiple interest collectors', async (context: IndigoTestContext) => {
    const [iAssetConfig] = context.assetConfigs;

    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await runAndAwaitTx(
      context.lucid,
      runOpenCdp(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        10_000_000n,
        500_000n,
      ),
    );

    context.emulator.awaitSlot(6500);

    await runFeedPriceToOracle(
      context,
      context.systemParams,
      iAssetConfig,
      adaAssetClass,
      rationalFromInt(1n),
    );

    const interestCollectors = await findAllInterestCollectors(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
    );

    const interestCollectorsUtxos = interestCollectors.filter(
      (utxo) =>
        assetClassValueOf(
          utxo.assets,
          fromSystemParamsAsset(
            context.systemParams.interestCollectionParams.multisigUtxoNft,
          ),
        ) === 0n,
    );
    if (interestCollectorsUtxos.length < 2) {
      throw new Error('Expected at least 2 interest collectors');
    }

    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    // This can fail in the CDP script or the interest collection script as the
    // check of single interest collector is redundant.
    await expectScriptFailure(
      'crashed',
      runTestDepositCdpWithInterestVar(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        interestCollectorsUtxos[0],
        {
          kind: 'CollectFromMultipleInterestCollectors',
          utxo: interestCollectorsUtxos[1],
        },
      ),
    );
  });

  test<IndigoTestContext>('Collect Interest - ADA and 3 assets', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    const [iAssetConfig] = context.assetConfigs;

    await runAndAwaitTx(
      context.lucid,
      runOpenCdp(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        10_000_000n,
        500_000n,
      ),
    );

    context.emulator.awaitSlot(6500);

    await runFeedPriceToOracle(
      context,
      context.systemParams,
      iAssetConfig,
      adaAssetClass,
      rationalFromInt(1n),
    );

    const interestCollectionUtxo = await findRandomNonAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await expectScriptFailure(
      'D',
      runTestDepositCdpWithInterestVar(
        context,
        context.systemParams,
        'iUSD',
        adaAssetClass,
        interestCollectionUtxo,
        {
          kind: 'CollectCustomValue',
          value: addAssets(
            mkLovelacesOf(1000000n),
            mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n),
            mkAssetsOf(EXAMPLE_TOKEN_2, 1_000n),
            mkAssetsOf(EXAMPLE_TOKEN_3, 1_000n),
          ),
        },
      ),
    );
  });

  // This test settles the biggest possible batch of CDPs
  test<IndigoTestContext>('Batch collect - 16 CDPs', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await createMultipleUtxosAtTreasury(
      mkLovelacesOf(2n),
      12n,
      context.systemParams,
      context,
    );

    const [iAssetConfig] = context.assetConfigs;

    const numberOfCdps = 16;

    await repeat(numberOfCdps, async () => {
      await runAndAwaitTx(
        context.lucid,
        runOpenCdp(
          context,
          context.systemParams,
          iAssetConfig.iassetTokenNameAscii,
          adaAssetClass,
          12_000_000n,
          6_000_000n,
        ),
      );
    });

    context.emulator.awaitSlot(
      Number(
        context.systemParams.interestCollectionParams
          .interestSettlementCooldown,
      ) / 1_000,
    );

    const orefs = await findAllNecessaryOrefs(
      context.lucid,
      context.systemParams,
      'iUSD',
      adaAssetClass,
    );

    const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
      context.lucid,
      orefs.collateralAsset,
    );

    const cdpsInfo = await findAllActiveCdps(
      context.lucid,
      context.systemParams,
      'iUSD',
      stakeCredentialOf(context.users.user.address),
    );

    expect(
      cdpsInfo.length === numberOfCdps,
      `Expected ${numberOfCdps} cdps`,
    ).toBeTruthy();

    context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);

    await runAndAwaitTx(
      context.lucid,
      feedPriceOracleTx(
        context.lucid,
        priceOracleUtxo!,
        rationalFromInt(1n),
        iAssetConfig.collateralAssets[0].oracleParams!,
        context.emulator.slot,
      ),
    );

    await benchmarkAndAwaitTx(
      'Interest Collection - Batch Collect 16 CDPs',
      await batchCollectInterest(
        orefs.collateralAsset.utxo,
        orefs.interestCollectorUtxo,
        orefs.interestOracleUtxo,
        cdpsInfo.map((cdp) => cdp.utxo),
        context.systemParams,
        context.lucid,
        context.emulator.slot,
      ),
      context.lucid,
      context.emulator,
    );
  });

  test<IndigoTestContext>('Batch collect fails when no cooldown elapsed', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await createMultipleUtxosAtTreasury(
      mkLovelacesOf(2n),
      10n,
      context.systemParams,
      context,
    );

    const [iAssetConfig] = context.assetConfigs;

    const numberOfCdps = 10;

    await repeat(numberOfCdps, async () => {
      await runAndAwaitTx(
        context.lucid,
        runOpenCdp(
          context,
          context.systemParams,
          iAssetConfig.iassetTokenNameAscii,
          adaAssetClass,
          12_000_000n,
          6_000_000n,
        ),
      );
    });

    // NOTE: Awaiting the cooldown period minus 39 seconds makes the transaction succeed,
    // this is probably due to the awaitTx time.
    context.emulator.awaitSlot(
      Number(
        context.systemParams.interestCollectionParams
          .interestSettlementCooldown,
      ) /
        1_000 -
        40,
    );

    const orefs = await findAllNecessaryOrefs(
      context.lucid,
      context.systemParams,
      'iUSD',
      adaAssetClass,
    );

    const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
      context.lucid,
      orefs.collateralAsset,
    );

    const cdpsInfo = await findAllActiveCdps(
      context.lucid,
      context.systemParams,
      'iUSD',
      stakeCredentialOf(context.users.user.address),
    );

    expect(
      cdpsInfo.length === numberOfCdps,
      `Expected ${numberOfCdps} cdps`,
    ).toBeTruthy();

    context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);

    await runAndAwaitTx(
      context.lucid,
      feedPriceOracleTx(
        context.lucid,
        priceOracleUtxo!,
        rationalFromInt(1n),
        iAssetConfig.collateralAssets[0].oracleParams!,
        context.emulator.slot,
      ),
    );

    await expectScriptFailure(
      'It is too soon to settle interest',
      batchCollectInterest(
        orefs.collateralAsset.utxo,
        orefs.interestCollectorUtxo,
        orefs.interestOracleUtxo,
        cdpsInfo.map((cdp) => cdp.utxo),
        context.systemParams,
        context.lucid,
        context.emulator.slot,
      ),
    );
  });

  test<IndigoTestContext>('Distribute', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await createUtxosAtInterestCollector(
      1,
      addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
      context.systemParams,
      context,
    );

    context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);

    const interestDistributeUtxo = matchSingle(
      (
        await findAllInterestCollectors(
          context.lucid,
          context.systemParams.validatorHashes.interestCollectionHash,
        )
      ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1)),
      (_) => new Error('Expected a single interest distribute UTXO'),
    );

    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    await benchmarkAndAwaitTx(
      'Interest Collection - Distribute',
      await distributeInterest(
        [interestDistributeUtxo],
        interestAdminUtxo,
        context.systemParams,
        context.lucid,
      ),
      context.lucid,
      context.emulator,
    );
  });

  test<IndigoTestContext>('Distribute from multiple collectors - 58', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    const numberOfInterestCollectionUtxos = 58;

    await createUtxosAtInterestCollector(
      numberOfInterestCollectionUtxos,
      addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
      context.systemParams,
      context,
    );

    context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);

    const interestDistributeUtxos = (
      await findAllInterestCollectors(
        context.lucid,
        context.systemParams.validatorHashes.interestCollectionHash,
      )
    ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1));

    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    await benchmarkAndAwaitTx(
      'Interest collection - Distribute from multiple collectors, 58',
      await distributeInterest(
        interestDistributeUtxos,
        interestAdminUtxo,
        context.systemParams,
        context.lucid,
      ),
      context.lucid,
      context.emulator,
    );
  });

  test<IndigoTestContext>('Distribute - No admin signature', async (context: IndigoTestContext) => {
    context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);

    await createUtxosAtInterestCollector(
      1,
      addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
      context.systemParams,
      context,
    );

    context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);

    const interestDistributeUtxo = matchSingle(
      (
        await findAllInterestCollectors(
          context.lucid,
          context.systemParams.validatorHashes.interestCollectionHash,
        )
      ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1)),
      (_) => new Error('Expected a single interest distribute UTXO'),
    );

    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    await expectScriptFailure(
      'Admin multisig must be satisfied',
      testDistributeInterest(
        interestDistributeUtxo,
        interestAdminUtxo,
        context.users.user.address,
        undefined,
        context.systemParams,
        context.lucid,
        { kind: 'DistributeInterestNoAdmin' },
      ),
    );
  });

  test<IndigoTestContext>('Update Permissions', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      Signature: {
        keyHash: fromHex(paymentCredentialOf(context.users.user.address).hash),
      },
    };

    await benchmarkAndAwaitTx(
      'Interest Collection - Update Permissions',
      await updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        [
          ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
          ...signersAllOf(newAdminPermissions),
        ],
        context.systemParams,
        context.lucid,
      ),
      context.lucid,
      context.emulator,
      [context.users.user.seedPhrase],
    );
  });

  test<IndigoTestContext>('Update Permissions - all of multiple signers', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      AtLeast: {
        required: 1n,
        authSignatories: [
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user.address).hash,
              ),
            },
          }),
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user2.address).hash,
              ),
            },
          }),
        ],
      },
    };

    await benchmarkAndAwaitTx(
      'Interest Collection - Update Permissions - all of multiple signers',
      await updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        [
          ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
          ...signersAllOf(newAdminPermissions),
        ],
        context.systemParams,
        context.lucid,
      ),
      context.lucid,
      context.emulator,
      [context.users.user.seedPhrase, context.users.user2.seedPhrase],
    );
  });

  test<IndigoTestContext>('Update Permissions - some of multiple signers', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      AtLeast: {
        required: 2n,
        authSignatories: [
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.admin.address).hash,
              ),
            },
          }),
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user.address).hash,
              ),
            },
          }),
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user2.address).hash,
              ),
            },
          }),
        ],
      },
    };

    await runAndAwaitTx(
      context.lucid,
      updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        [
          ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
          ...[paymentCredentialOf(context.users.user.address).hash],
        ],
        context.systemParams,
        context.lucid,
      ),
      [context.users.user.seedPhrase],
    );
  });

  test<IndigoTestContext>('Update Permissions - nested multisig', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      AtLeast: {
        required: 2n,
        authSignatories: [
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.admin.address).hash,
              ),
            },
          }),
          toDataMultisig({
            AtLeast: {
              required: 1n,
              authSignatories: [
                toDataMultisig({
                  Signature: {
                    keyHash: fromHex(
                      paymentCredentialOf(context.users.user.address).hash,
                    ),
                  },
                }),
                toDataMultisig({
                  Signature: {
                    keyHash: fromHex(
                      paymentCredentialOf(context.users.user2.address).hash,
                    ),
                  },
                }),
              ],
            },
          }),
        ],
      },
    };

    await runAndAwaitTx(
      context.lucid,
      updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        [
          ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
          ...[paymentCredentialOf(context.users.user.address).hash],
        ],
        context.systemParams,
        context.lucid,
      ),
      [context.users.user.seedPhrase],
    );
  });

  test<IndigoTestContext>('Update Permissions - Fail when new admin is not signed', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      Signature: {
        keyHash: fromHex(paymentCredentialOf(context.users.user.address).hash),
      },
    };

    await expectScriptFailure(
      'New admin multisig must be satisfied',
      updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
        context.systemParams,
        context.lucid,
      ),
    );
  });

  test<IndigoTestContext>('Update Permissions - Fail when not enough signers of new admin', async (context: IndigoTestContext) => {
    const interestAdminUtxo = await findAdminInterestCollector(
      context.lucid,
      context.systemParams.validatorHashes.interestCollectionHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.multisigUtxoNft,
      ),
    );

    const govUtxo = await findGov(
      context.lucid,
      context.systemParams.validatorHashes.govHash,
      fromSystemParamsAsset(
        context.systemParams.interestCollectionParams.govAuthTk,
      ),
    );

    const newAdminPermissions = {
      AtLeast: {
        required: 2n,
        authSignatories: [
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.admin.address).hash,
              ),
            },
          }),
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user.address).hash,
              ),
            },
          }),
          toDataMultisig({
            Signature: {
              keyHash: fromHex(
                paymentCredentialOf(context.users.user2.address).hash,
              ),
            },
          }),
        ],
      },
    };

    await expectScriptFailure(
      'New admin multisig must be satisfied',
      updatePermissions(
        interestAdminUtxo,
        govUtxo.utxo,
        newAdminPermissions,
        signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
        context.systemParams,
        context.lucid,
      ),
    );
  });
});
