/* eslint-disable no-console */
import { expect } from 'chai';
import { before, describe, it } from 'mocha';
import { IsmType } from '@hyperlane-xyz/provider-sdk/altvm';
import { ArtifactState, } from '@hyperlane-xyz/provider-sdk/artifact';
import { assert } from '@hyperlane-xyz/utils';
import { SvmSigner } from '../clients/signer.js';
import { SvmIsmArtifactManager } from '../ism/ism-artifact-manager.js';
import { SvmMessageIdMultisigIsmReader, SvmMessageIdMultisigIsmWriter, } from '../ism/multisig-ism.js';
import { SvmTestIsmReader, SvmTestIsmWriter } from '../ism/test-ism.js';
import { createRpc } from '../rpc.js';
import { TEST_SVM_CHAIN_METADATA } from '../testing/constants.js';
import { TEST_PROGRAM_IDS, airdropSol } from '../testing/setup.js';
import { address } from '@solana/kit';
const TEST_PRIVATE_KEY = '0x0000000000000000000000000000000000000000000000000000000000000001';
describe('SVM ISM E2E Tests', function () {
    this.timeout(180_000);
    let rpc;
    let signer;
    before(async () => {
        rpc = createRpc(TEST_SVM_CHAIN_METADATA.rpcUrl);
        signer = await SvmSigner.connectWithSigner([TEST_SVM_CHAIN_METADATA.rpcUrl], TEST_PRIVATE_KEY);
        await airdropSol(rpc, address(signer.getSignerAddress()));
    });
    describe('Test ISM', () => {
        it('should initialize and read Test ISM', async function () {
            const writer = new SvmTestIsmWriter({ program: { programId: TEST_PROGRAM_IDS.testIsm } }, rpc, signer);
            let deployed, receipts;
            try {
                [deployed, receipts] = await writer.create({
                    artifactState: ArtifactState.NEW,
                    config: { type: IsmType.TEST_ISM },
                });
            }
            catch (err) {
                const msg = err instanceof Error ? err.message : String(err);
                if (msg.includes('ProgramFailedToComplete') ||
                    msg.includes('Access violation')) {
                    console.log('Skipping: Test ISM binary incompatible with validator');
                    this.skip();
                    return;
                }
                throw err;
            }
            expect(receipts).to.have.length.greaterThan(0);
            expect(deployed.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(deployed.config.type).to.equal(IsmType.TEST_ISM);
            expect(deployed.deployed.address).to.equal(TEST_PROGRAM_IDS.testIsm);
            expect(deployed.deployed.programId).to.equal(TEST_PROGRAM_IDS.testIsm);
            const reader = new SvmTestIsmReader(rpc);
            const readResult = await reader.read(TEST_PROGRAM_IDS.testIsm);
            expect(readResult.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(readResult.config.type).to.equal(IsmType.TEST_ISM);
        });
        it('should return empty transactions for update', async () => {
            const writer = new SvmTestIsmWriter({ program: { programId: TEST_PROGRAM_IDS.testIsm } }, rpc, signer);
            const artifact = {
                artifactState: ArtifactState.DEPLOYED,
                config: { type: IsmType.TEST_ISM },
                deployed: {
                    address: TEST_PROGRAM_IDS.testIsm,
                    programId: TEST_PROGRAM_IDS.testIsm,
                },
            };
            const updateTxs = await writer.update(artifact);
            expect(updateTxs).to.have.length(0);
        });
    });
    describe('Multisig ISM', () => {
        it('should create and read Multisig ISM with domain configs', async function () {
            const writer = new SvmMessageIdMultisigIsmWriter(rpc, signer);
            const config = {
                type: IsmType.MESSAGE_ID_MULTISIG,
                validators: [],
                threshold: 0,
                program: { programId: TEST_PROGRAM_IDS.multisigIsm },
                domains: {
                    1: {
                        validators: [
                            '0x1111111111111111111111111111111111111111',
                            '0x2222222222222222222222222222222222222222',
                            '0x3333333333333333333333333333333333333333',
                        ],
                        threshold: 2,
                    },
                    137: {
                        validators: [
                            '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
                            '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
                        ],
                        threshold: 1,
                    },
                },
            };
            const [deployed, receipts] = await writer.create({
                artifactState: ArtifactState.NEW,
                config,
            });
            expect(receipts).to.have.length.greaterThan(0);
            expect(deployed.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(deployed.config.type).to.equal(IsmType.MESSAGE_ID_MULTISIG);
            const reader = new SvmMessageIdMultisigIsmReader(rpc);
            const readResult = await reader.read(TEST_PROGRAM_IDS.multisigIsm);
            expect(readResult.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(readResult.config.type).to.equal(IsmType.MESSAGE_ID_MULTISIG);
            const domain1 = await reader.readDomain(TEST_PROGRAM_IDS.multisigIsm, 1);
            assert(domain1, 'expected domain1 to exist');
            expect(domain1.threshold).to.equal(2);
            expect(domain1.validators).to.have.length(3);
            const domain137 = await reader.readDomain(TEST_PROGRAM_IDS.multisigIsm, 137);
            assert(domain137, 'expected domain137 to exist');
            expect(domain137.threshold).to.equal(1);
            expect(domain137.validators).to.have.length(2);
        });
    });
    describe('ISM Artifact Manager', () => {
        it('should detect ISM type from address', async function () {
            const manager = new SvmIsmArtifactManager(rpc);
            try {
                const testIsmArtifact = await manager.readIsm(TEST_PROGRAM_IDS.testIsm);
                expect(testIsmArtifact.config.type).to.equal(IsmType.TEST_ISM);
            }
            catch (err) {
                const msg = err instanceof Error ? err.message : String(err);
                if (msg.includes('Unable to detect ISM type')) {
                    // Test ISM binary may be incompatible; verify multisig detection works
                    const multisigArtifact = await manager.readIsm(TEST_PROGRAM_IDS.multisigIsm);
                    expect(multisigArtifact.config.type).to.equal(IsmType.MESSAGE_ID_MULTISIG);
                }
                else {
                    throw err;
                }
            }
        });
        it('should create readers for different ISM types', () => {
            const manager = new SvmIsmArtifactManager(rpc);
            const testIsmReader = manager.createReader(IsmType.TEST_ISM);
            expect(testIsmReader).to.be.instanceOf(SvmTestIsmReader);
        });
        it('should create writers for different ISM types', () => {
            const manager = new SvmIsmArtifactManager(rpc);
            const testIsmWriter = manager.createWriter(IsmType.TEST_ISM, signer);
            expect(testIsmWriter).to.be.instanceOf(SvmTestIsmWriter);
        });
    });
});
//# sourceMappingURL=ism.e2e-test.js.map