import { describe, expect, it } from 'vitest';
import { MessageSigner, MLDSASecurityLevel, Mnemonic } from '../build/opnet.js';
import { networks, toHex } from '@btc-vision/bitcoin';

describe('MessageSigner Schnorr', () => {
    const testMnemonic =
        'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';

    describe('sha256', () => {
        it('should hash a string message', () => {
            const message = 'Hello, OPNet!';
            const hash = MessageSigner.sha256(Buffer.from(message, 'utf-8'));

            expect(hash).toBeInstanceOf(Uint8Array);
            expect(hash.length).toBe(32);
        });

        it('should hash a Buffer message', () => {
            const message = Buffer.from('Hello, Buffer!', 'utf-8');
            const hash = MessageSigner.sha256(message);

            expect(hash).toBeInstanceOf(Uint8Array);
            expect(hash.length).toBe(32);
        });

        it('should hash a Uint8Array message', () => {
            const message = new Uint8Array([1, 2, 3, 4, 5]);
            const hash = MessageSigner.sha256(message);

            expect(hash).toBeInstanceOf(Uint8Array);
            expect(hash.length).toBe(32);
        });

        it('should produce consistent hashes for same input', () => {
            const message = 'Test message';
            const hash1 = MessageSigner.sha256(Buffer.from(message, 'utf-8'));
            const hash2 = MessageSigner.sha256(Buffer.from(message, 'utf-8'));

            expect(toHex(hash1)).toBe(toHex(hash2));
        });

        it('should produce different hashes for different inputs', () => {
            const message1 = 'Message 1';
            const message2 = 'Message 2';
            const hash1 = MessageSigner.sha256(Buffer.from(message1, 'utf-8'));
            const hash2 = MessageSigner.sha256(Buffer.from(message2, 'utf-8'));

            expect(toHex(hash1)).not.toBe(toHex(hash2));
        });

        it('should hash empty message', () => {
            const message = Buffer.alloc(0);
            const hash = MessageSigner.sha256(message);

            expect(hash).toBeInstanceOf(Uint8Array);
            expect(hash.length).toBe(32);
        });
    });

    describe('signMessage - string input', () => {
        it('should sign a UTF-8 string message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Hello, OPNet!';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature).toBeInstanceOf(Uint8Array);
            expect(signed.signature.length).toBe(64); // Schnorr signatures are 64 bytes
            expect(signed.message).toBeInstanceOf(Uint8Array);
            expect(signed.message.length).toBe(32); // SHA-256 hash
        });

        it('should sign an empty string', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = '';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a very long string', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'A'.repeat(10000);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a string with special characters', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = '!@#$%^&*()_+-=[]{}|;:",.<>?/~`\n\t\r';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a Unicode string', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = '你好世界 🌍 مرحبا العالم';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });
    });

    describe('signMessage - Buffer input', () => {
        it('should sign a Buffer message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from('Hello, Buffer!', 'utf-8');
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature).toBeInstanceOf(Uint8Array);
            expect(signed.signature.length).toBe(64);
            expect(signed.message).toBeInstanceOf(Uint8Array);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a Buffer with binary data', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from([0x00, 0x01, 0x02, 0xff, 0xfe, 0xfd]);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a Buffer created from hex', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from('deadbeef', 'hex');
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign an empty Buffer', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.alloc(0);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });
    });

    describe('signMessage - Uint8Array input', () => {
        it('should sign a Uint8Array message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array([1, 2, 3, 4, 5]);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature).toBeInstanceOf(Uint8Array);
            expect(signed.signature.length).toBe(64);
            expect(signed.message).toBeInstanceOf(Uint8Array);
            expect(signed.message.length).toBe(32);
        });

        it('should sign a Uint8Array with all byte values', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array(256);
            for (let i = 0; i < 256; i++) {
                message[i] = i;
            }

            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign an empty Uint8Array', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array(0);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });
    });

    describe('signMessage - signature uniqueness', () => {
        it('should produce different signatures for different messages', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message1 = 'First message';
            const message2 = 'Second message';

            const signed1 = MessageSigner.signMessage(wallet.keypair, message1);
            const signed2 = MessageSigner.signMessage(wallet.keypair, message2);

            expect(Buffer.from(signed1.signature).toString('hex')).not.toBe(
                Buffer.from(signed2.signature).toString('hex'),
            );
        });

        it('should produce different signatures for different keypairs', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet1 = mnemonic.derive(0);
            const wallet2 = mnemonic.derive(1);

            const message = 'Same message';

            const signed1 = MessageSigner.signMessage(wallet1.keypair, message);
            const signed2 = MessageSigner.signMessage(wallet2.keypair, message);

            expect(Buffer.from(signed1.signature).toString('hex')).not.toBe(
                Buffer.from(signed2.signature).toString('hex'),
            );
        });

        it('should hash the message before signing', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const expectedHash = MessageSigner.sha256(Buffer.from(message, 'utf-8'));
            expect(toHex(signed.message)).toBe(toHex(expectedHash));
        });
    });

    describe('verifySignature - string input', () => {
        it('should verify a valid signature with string message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Hello, OPNet!';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should verify signature with Unicode string', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = '你好世界 🌍';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should fail verification with wrong message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Hello, OPNet!';
            const wrongMessage = 'Wrong message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                wrongMessage,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });
    });

    describe('verifySignature - Buffer input', () => {
        it('should verify a valid signature with Buffer message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from('Hello, Buffer!', 'utf-8');
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should verify signature with binary Buffer', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from([0x00, 0x01, 0x02, 0xff]);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });
    });

    describe('verifySignature - Uint8Array input', () => {
        it('should verify a valid signature with Uint8Array message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array([1, 2, 3, 4, 5]);
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should verify signature with Uint8Array public key', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const publicKeyUint8 = new Uint8Array(wallet.keypair.publicKey);
            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                publicKeyUint8,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });
    });

    describe('verifySignature - error cases', () => {
        it('should throw error for invalid signature length', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const invalidSignature = Buffer.alloc(32); // Wrong length

            expect(() => {
                MessageSigner.verifySignature(wallet.keypair.publicKey, message, invalidSignature);
            }).toThrow('Invalid signature length');
        });

        it('should fail verification with wrong public key', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet1 = mnemonic.derive(0);
            const wallet2 = mnemonic.derive(1);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet1.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet2.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });

        it('should fail verification with corrupted signature', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const corruptedSignature = Buffer.from(signed.signature);
            corruptedSignature[0] = (corruptedSignature[0] as number) ^ 0xff;

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                corruptedSignature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });
    });

    describe('tweakAndSignMessage', () => {
        it('should sign a message with tweaked keypair', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Hello, Tweaked OPNet!';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            expect(signed.signature).toBeInstanceOf(Uint8Array);
            expect(signed.signature.length).toBe(64);
            expect(signed.message).toBeInstanceOf(Uint8Array);
            expect(signed.message.length).toBe(32);
        });

        it('should sign with tweaked key - string message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test tweaked';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign with tweaked key - Buffer message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from('Test tweaked buffer', 'utf-8');
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should sign with tweaked key - Uint8Array message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array([1, 2, 3, 4, 5]);
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            expect(signed.signature.length).toBe(64);
            expect(signed.message.length).toBe(32);
        });

        it('should produce different signature than non-tweaked', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Compare tweaked vs non-tweaked';
            const signed = MessageSigner.signMessage(wallet.keypair, message);
            const tweakedSigned = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            expect(Buffer.from(signed.signature).toString('hex')).not.toBe(
                Buffer.from(tweakedSigned.signature).toString('hex'),
            );
        });

        it('should work on different networks', () => {
            const networks_list = [networks.bitcoin, networks.testnet, networks.opnetTestnet, networks.regtest];

            for (const network of networks_list) {
                const mnemonic = new Mnemonic(testMnemonic, '', network, MLDSASecurityLevel.LEVEL2);
                const wallet = mnemonic.derive(0);

                const message = 'Test network ' + network.bech32;
                const signed = MessageSigner.tweakAndSignMessage(wallet.keypair, message, network);

                expect(signed.signature.length).toBe(64);
                expect(signed.message.length).toBe(32);
            }
        });
    });

    describe('tweakAndVerifySignature', () => {
        it('should verify a tweaked signature', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test tweaked verification';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should verify tweaked signature with Buffer message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from('Test tweaked buffer', 'utf-8');
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should verify tweaked signature with Uint8Array message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = new Uint8Array([5, 4, 3, 2, 1]);
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should fail verification with wrong message', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Correct message';
            const wrongMessage = 'Wrong message';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                wrongMessage,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });

        it('should fail verification with wrong public key', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet1 = mnemonic.derive(0);
            const wallet2 = mnemonic.derive(1);

            const message = 'Test message';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet1.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet2.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });

        it('should not verify non-tweaked signature with tweakAndVerifySignature', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });

        it('should verify with Uint8Array public key', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const publicKeyUint8 = new Uint8Array(wallet.keypair.publicKey);
            const isValidLegacyPublicKey = MessageSigner.tweakAndVerifySignature(
                publicKeyUint8,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });
    });

    describe('cross-validation between tweaked and non-tweaked', () => {
        it('should not cross-verify tweaked signature with regular verify', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const tweakedSigned = MessageSigner.tweakAndSignMessage(
                wallet.keypair,
                message,
                networks.bitcoin,
            );

            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                tweakedSigned.signature,
            );

            expect(isValidLegacyPublicKey).toBe(false);
        });

        it('should verify regular signature with regular verify, not with tweaked verify', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'Test message';
            const signed = MessageSigner.signMessage(wallet.keypair, message);

            const isValidRegular = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );
            const isValidTweaked = MessageSigner.tweakAndVerifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidRegular).toBe(true);
            expect(isValidTweaked).toBe(false);
        });
    });

    describe('network-specific tweaked signatures', () => {
        it('should produce different tweaked signatures for different networks', () => {
            const message = 'Network test';

            const mnemonicMainnet = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const mnemonicTestnet = new Mnemonic(
                testMnemonic,
                '',
                networks.testnet,
                MLDSASecurityLevel.LEVEL2,
            );

            const walletMainnet = mnemonicMainnet.derive(0);
            const walletTestnet = mnemonicTestnet.derive(0);

            const signedMainnet = MessageSigner.tweakAndSignMessage(
                walletMainnet.keypair,
                message,
                networks.bitcoin,
            );
            const signedTestnet = MessageSigner.tweakAndSignMessage(
                walletTestnet.keypair,
                message,
                networks.testnet,
            );

            // Signatures should be different
            expect(Buffer.from(signedMainnet.signature).toString('hex')).not.toBe(
                Buffer.from(signedTestnet.signature).toString('hex'),
            );

            // Each should verify with its own network's tweaked key
            expect(
                MessageSigner.tweakAndVerifySignature(
                    walletMainnet.keypair.publicKey,
                    message,
                    signedMainnet.signature,
                ),
            ).toBe(true);
            expect(
                MessageSigner.tweakAndVerifySignature(
                    walletTestnet.keypair.publicKey,
                    message,
                    signedTestnet.signature,
                ),
            ).toBe(true);
        });
    });

    describe('message format edge cases', () => {
        it('should handle messages with null bytes', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = Buffer.from([0x00, 0x01, 0x00, 0x02, 0x00]);
            const signed = MessageSigner.signMessage(wallet.keypair, message);
            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should handle very long messages', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = 'X'.repeat(100000);
            const signed = MessageSigner.signMessage(wallet.keypair, message);
            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });

        it('should handle messages with emoji', () => {
            const mnemonic = new Mnemonic(
                testMnemonic,
                '',
                networks.bitcoin,
                MLDSASecurityLevel.LEVEL2,
            );
            const wallet = mnemonic.derive(0);

            const message = '🚀🌙⭐🪐💫';
            const signed = MessageSigner.signMessage(wallet.keypair, message);
            const isValidLegacyPublicKey = MessageSigner.verifySignature(
                wallet.keypair.publicKey,
                message,
                signed.signature,
            );

            expect(isValidLegacyPublicKey).toBe(true);
        });
    });
});
