import { expect, describe, it, jest } from "@jest/globals";
import { solana } from "../../../../src/domain/entities";
import { solanaTransferRedeemedMapper } from "../../../../src/infrastructure/mappers";
import { getPostedMessage } from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";

jest.mock("@certusone/wormhole-sdk/lib/cjs/solana/wormhole");

describe("solanaTransferRedeemedMapper", () => {
  it("should map a token bridge tx to a transfer-redeemed event", async () => {
    const mockGetPostedMessage = getPostedMessage as jest.MockedFunction<typeof getPostedMessage>;
    mockGetPostedMessage.mockResolvedValueOnce({
      message: {
        emitterChain: 2,
        sequence: 1500n,
        emitterAddress: Buffer.from(
          "0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585",
          "hex"
        ),
        submissionTime: 1700571923,
        nonce: 0,
        consistencyLevel: 1,
        payload: Buffer.from("41QVZTrdrRxb", "base64"),
      } as any,
    });

    const programId = "wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb";
    const tx = {
      blockTime: 1701724272,
      meta: {
        innerInstructions: [
          {
            index: 0,
            instructions: [
              {
                accounts: [0, 3],
                data: "3Bxs49175da2o1zw",
                programIdIndex: 4,
                stackHeight: 2,
              },
              {
                accounts: [3],
                data: "9krTCzbLfv4BRBcj",
                programIdIndex: 4,
                stackHeight: 2,
              },
              {
                accounts: [3],
                data: "SYXsBvR59hMYH7jGFg8pjr13roqCKDy5t1HFBVKFNWZ1FPp7",
                programIdIndex: 4,
                stackHeight: 2,
              },
              {
                accounts: [2, 1, 6],
                data: "6jFrQ56LiKZ1",
                programIdIndex: 11,
                stackHeight: 2,
              },
              {
                accounts: [2, 1, 6],
                data: "6AjePwYNteRu",
                programIdIndex: 11,
                stackHeight: 2,
              },
            ],
          },
        ],
        logMessages: [
          "Program wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb invoke [1]",
          "Program 11111111111111111111111111111111 invoke [2]",
          "Program 11111111111111111111111111111111 success",
          "Program 11111111111111111111111111111111 invoke [2]",
          "Program 11111111111111111111111111111111 success",
          "Program 11111111111111111111111111111111 invoke [2]",
          "Program 11111111111111111111111111111111 success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: MintTo",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4492 of 136305 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: MintTo",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4589 of 125187 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb consumed 80797 of 200000 compute units",
          "Program wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb success",
        ],
        status: {
          Ok: null,
        },
      },
      slot: 234015120,
      transaction: {
        message: {
          header: {
            numReadonlySignedAccounts: 0,
            numReadonlyUnsignedAccounts: 10,
            numRequiredSignatures: 1,
          },
          accountKeys: [
            "7dm9am6Qx7cH64RB99Mzf7ZsLbEfmXM7ihXXCvMiT2X1",
            "4RrFMkY3A5zWdizT61Px222qmSTJqnVszDeBZZNSoAH6",
            "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
            "HkpTbh5td45g3SfFsKmjukX2YZUKfEHZG5HfRrw6Tkyi",
            "11111111111111111111111111111111",
            "2gQuwC9GMUCVcXw9VffeCswhKbPeyzHH9ZPEnRBw4K9w",
            "BCD75RNBHrJJpW4dXVagL5mPjzRLnVZq4YirJdjEYMV7",
            "CvYA8s1SnSzQzCv71rjt7Sc9iEVNjz2exRpoucyH2RCE",
            "DapiQYH3BGonhN8cngWcXQ6SrqSm3cwysoznoHr6Sbsx",
            "DujfLgMKW71CT2W8pxknf42FT86VbcK5PjQ6LsutjWKC",
            "SysvarRent111111111111111111111111111111111",
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
            "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth",
            "wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb",
          ],
          recentBlockhash: "H9bDwcfav3nq9wvzJi9sEPCm4oHxqS59nZU81mncD6AU",
          instructions: [
            {
              accounts: [0, 8, 7, 3, 9, 1, 1, 2, 5, 6, 10, 4, 11, 12],
              data: "4",
              programIdIndex: 13,
              stackHeight: null,
            },
          ],
          indexToProgramIds: {},
          compiledInstructions: [
            {
              programIdIndex: 13,
              accountKeyIndexes: [0, 8, 7, 3, 9, 1, 1, 2, 5, 6, 10, 4, 11, 12],
              data: new Uint8Array([3]),
            },
          ],
        },
        signatures: [
          "3FySmshUgVCM2N158oNYbeTfZt2typEU32c9ZxdAXiXURFHuTmeJHhc7cSUtqHdwAsbVWWvEsEddWNAKzkjVPSg2",
        ],
      },
      version: "legacy",
    } as any as solana.Transaction;

    const events = await solanaTransferRedeemedMapper(tx, { programId });

    expect(events).toHaveLength(1);
    expect(events[0].name).toBe("transfer-redeemed");
    expect(events[0].address).toBe(programId);
    expect(events[0].chainId).toBe(1);
    expect(events[0].txHash).toBe(tx.transaction.signatures[0]);
    expect(events[0].blockHeight).toBe(BigInt(tx.slot));
    expect(events[0].blockTime).toBe(tx.blockTime);
  });

  it("should map a tx involving token bridge relayer (aka connect) to a transfer-redeemed event", async () => {
    const mockGetPostedMessage = getPostedMessage as jest.MockedFunction<typeof getPostedMessage>;
    mockGetPostedMessage.mockResolvedValueOnce({
      message: {
        emitterChain: 4,
        sequence: 5185,
        emitterAddress: Buffer.from(
          "0000000000000000000000009dcf9d205c9de35334d646bee44b2d2859712a09",
          "hex"
        ),
        submissionTime: 1700571923,
        nonce: 0,
        consistencyLevel: 1,
        payload: Buffer.from("41QVZTrdrRxb", "base64"),
      } as any,
    });

    const programId = "DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe";
    const tx = {
      blockTime: 1701701948,
      meta: {
        innerInstructions: [
          {
            index: 0,
            instructions: [
              {
                accounts: [0, 1],
                data: "11119os1e9qSs2u7TsThXqkBSRVFxhmYaFKFZ1waB2X7armDmvK3p5GmLdUxYdg3h7QSrL",
                programIdIndex: 7,
                stackHeight: 2,
              },
              {
                accounts: [1, 4],
                data: "6NejZzEkDLeuHiYpvQR3Ck46Sw6FQeXFmX5TGWpBSLgJ1",
                programIdIndex: 22,
                stackHeight: 2,
              },
              {
                accounts: [0, 15, 8, 5, 16, 1, 9, 1, 4, 12, 20, 21, 7, 11, 22],
                data: "B",
                programIdIndex: 18,
                stackHeight: 2,
              },
              {
                accounts: [0, 5],
                data: "11112ncWAFpbecrgZiGiLpaHnEYkj7ECUfBBRHr4H5tFCq9bHFXWRyWUjj586frtFc19oa",
                programIdIndex: 7,
                stackHeight: 3,
              },
              {
                accounts: [4, 1, 20],
                data: "6j1A9VR8zuFm",
                programIdIndex: 22,
                stackHeight: 3,
              },
              {
                accounts: [1, 2, 9],
                data: "3tMLEJ9BQpG7",
                programIdIndex: 22,
                stackHeight: 2,
              },
              {
                accounts: [1, 6, 9],
                data: "3qeniiQUmAqm",
                programIdIndex: 22,
                stackHeight: 2,
              },
              {
                accounts: [1, 0, 9],
                data: "A",
                programIdIndex: 22,
                stackHeight: 2,
              },
            ],
          },
        ],
        loadedAddresses: {
          readonly: [],
          writable: [],
        },
        logMessages: [
          "Program 3bPRWXqtSfUaCw3S4wdgvypQtsSzcmvDeaqSqPDkncrg invoke [1]",
          "Program log: Instruction: CompleteWrappedTransferWithRelay",
          "Program 11111111111111111111111111111111 invoke [2]",
          "Program 11111111111111111111111111111111 success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: InitializeAccount3",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4214 of 223786 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe invoke [2]",
          "Program log: Instruction: LegacyCompleteTransferWithPayloadWrapped",
          "Program 11111111111111111111111111111111 invoke [3]",
          "Program 11111111111111111111111111111111 success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]",
          "Program log: Instruction: MintTo",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4492 of 128286 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe consumed 50570 of 173121 compute units",
          "Program DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: Transfer",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 119156 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: Transfer",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 111686 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
          "Program log: Instruction: CloseAccount",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 3015 of 104235 compute units",
          "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
          "Program 3bPRWXqtSfUaCw3S4wdgvypQtsSzcmvDeaqSqPDkncrg consumed 150503 of 250000 compute units",
          "Program 3bPRWXqtSfUaCw3S4wdgvypQtsSzcmvDeaqSqPDkncrg success",
          "Program ComputeBudget111111111111111111111111111111 invoke [1]",
          "Program ComputeBudget111111111111111111111111111111 success",
        ],
        status: {
          Ok: null,
        },
      },
      slot: 262968784,
      transaction: {
        message: {
          header: {
            numReadonlySignedAccounts: 0,
            numReadonlyUnsignedAccounts: 16,
            numRequiredSignatures: 1,
          },
          accountKeys: [
            "hiUN9rS9VTPVGYc71Vf2d6iyFLvsQaSsqWhxydqdaZf",
            "14UpGeFGK9iEhVTgMbdd7RHZmBKb8BYxBpAYGtBWigeT",
            "3pjtJPtu7Z9NzQinCaaRyUsZPwSrNjGxYi7RMwkigk47",
            "8DW7zrpEe9EVxbD8PBfmEKNkCwXPFTVVukHXirrcE9iV",
            "BaGfF51MQ3a61papTRDYaNefBgTQ9ywnVne5fCff4bxT",
            "bMDMKEYXfWM2h5AyJL4kzBXLr8Wms29NSWeGQGLgEad",
            "EGdE1V4GLFyZH5FFDtsxZaRkw84WhwPWJkCV4yT2L6F4",
            "11111111111111111111111111111111",
            "2EqgRpRxi1MR8QLycFDcMKws1Kv56dQcwSmXKkFJZgnW",
            "2X2u43DR3odTT4jQKFqsG5f4SCfbEmz4pAHR2EVd3Xs3",
            "3bPRWXqtSfUaCw3S4wdgvypQtsSzcmvDeaqSqPDkncrg",
            "3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5",
            "5rmBUDWruRcWU4S4JyjPLZhcYJARYw4FeU9brEo4nUzo",
            "7pFgBNscwYBfKs1Bsi7wgyibmtNCmK4442pgL4xiJcTr",
            "8huuoQHYxWGs3oYoKXJBsBgPousVa9XfkPyHWrpPH1B8",
            "8PFZNjn19BBYVHNp4H31bEW7eAmu78Yf2RKV8EeA461K",
            "9A7Z7kJw7hPsBJQDSeFU63DsgZGhSTjXmGLYS81yCHBN",
            "ComputeBudget111111111111111111111111111111",
            "DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe",
            "HeMY4WFgEA8zkbp7HMCma5mswLArPzPe53EkYcXDJTUV",
            "rRsXLHe7sBHdyKU3KY3wbcgWvoT1Ntqudf6e9PKusgb",
            "SysvarRent111111111111111111111111111111111",
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          ],
          recentBlockhash: "KVvqcsFkfd4mgWjqjsEATKvciAwCwUgdeVHeRh4LqyT",
          instructions: [
            {
              accounts: [0, 9, 2, 19, 4, 6, 3, 13, 14, 1, 12, 15, 8, 5, 16, 20, 11, 18, 7, 22, 21],
              data: "9ewcWKkpwjKSXZao88ZRqjejhWC1Bf6cFzdxHbDN4taHHCL3zM9P3xi",
              programIdIndex: 10,
              stackHeight: null,
            },
            {
              accounts: [],
              data: "HnkkG7",
              programIdIndex: 17,
              stackHeight: null,
            },
          ],
          indexToProgramIds: {},
          compiledInstructions: [
            {
              programIdIndex: 10,
              accountKeyIndexes: [
                0, 9, 2, 19, 4, 6, 3, 13, 14, 1, 12, 15, 8, 5, 16, 20, 11, 18, 7, 22, 21,
              ],
              data: new Uint8Array([
                174, 44, 4, 91, 81, 201, 235, 255, 59, 128, 71, 194, 194, 46, 49, 88, 200, 5, 254,
                175, 217, 196, 30, 63, 1, 233, 245, 96, 162, 12, 73, 62, 205, 171, 142, 159, 18, 6,
                57, 151,
              ]),
            },
            {
              programIdIndex: 17,
              accountKeyIndexes: [],
              data: new Uint8Array([2, 144, 208, 3, 0]),
            },
          ],
        },
        signatures: [
          "5Cu3tD15AtcQ5NGK6PFT9UMVmqh94ARz8FXpFts5G1nNzQnXXaugP3ELa79P9xCwESC5Kw7FtGHUgh7vz8DuP8tM",
        ],
      },

      version: "legacy",
    } as any as solana.Transaction;

    const events = await solanaTransferRedeemedMapper(tx, { programId });

    expect(events).toHaveLength(1);
    expect(events[0].name).toBe("transfer-redeemed");
    expect(events[0].address).toBe(programId);
    expect(events[0].chainId).toBe(1);
    expect(events[0].txHash).toBe(tx.transaction.signatures[0]);
    expect(events[0].blockHeight).toBe(BigInt(tx.slot));
    expect(events[0].blockTime).toBe(tx.blockTime);
  });
});
