import algosdk from 'algosdk';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { getAlgodClient, extractNetwork } from '../algorand-client.js';
import { withCommonParams } from './commonParams.js';
// Tool schemas
export const accountToolSchemas = {
    createAccount: {
        type: 'object',
        properties: {},
        required: []
    },
    rekeyAccount: {
        type: 'object',
        properties: {
            sourceAddress: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
            targetAddress: { type: 'string', description: 'Address to rekey the sender account to' }
        },
        required: ['sourceAddress', 'targetAddress']
    },
    mnemonicToMdk: {
        type: 'object',
        properties: {
            mnemonic: { type: 'string', description: 'The mnemonic phrase to convert to a master derivation key' }
        },
        required: ['mnemonic']
    },
    mdkToMnemonic: {
        type: 'object',
        properties: {
            mdk: { type: 'string', description: 'The master derivation key in hexadecimal format' }
        },
        required: ['mdk']
    },
    secretKeyToMnemonic: {
        type: 'object',
        properties: {
            secretKey: { type: 'string', description: 'The secret key in hexadecimal format' }
        },
        required: ['secretKey']
    },
    mnemonicToSecretKey: {
        type: 'object',
        properties: {
            mnemonic: { type: 'string', description: 'The mnemonic phrase to convert to a secret key' }
        },
        required: ['mnemonic']
    },
    seedFromMnemonic: {
        type: 'object',
        properties: {
            mnemonic: { type: 'string', description: 'The mnemonic phrase to generate a seed from' }
        },
        required: ['mnemonic']
    },
    mnemonicFromSeed: {
        type: 'object',
        properties: {
            seed: { type: 'string', description: 'The seed in hexadecimal format to generate a mnemonic from' }
        },
        required: ['seed']
    }
};
export class AccountManager {
    // Tool handlers
    static async handleTool(name, args) {
        try {
            switch (name) {
                case 'create_account':
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify(AccountManager.createAccount(), null, 2),
                            }],
                    };
                case 'rekey_account':
                    if (!args.sourceAddress || !args.targetAddress ||
                        typeof args.sourceAddress !== 'string' ||
                        typeof args.targetAddress !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Invalid rekey account parameters');
                    }
                    const network = extractNetwork(args);
                    const rekeyTxn = await AccountManager.createRekeyTransaction(args.sourceAddress, args.targetAddress, network);
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify(rekeyTxn, null, 2),
                            }],
                    };
                case 'mnemonic_to_mdk':
                    if (!args.mnemonic || typeof args.mnemonic !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Mnemonic is required');
                    }
                    const mdk = AccountManager.mnemonicToMasterDerivationKey(args.mnemonic);
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({ mdk: algosdk.bytesToHex(mdk) }, null, 2),
                            }],
                    };
                case 'mdk_to_mnemonic':
                    if (!args.mdk || typeof args.mdk !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Master derivation key is required');
                    }
                    const mdkMnemonic = AccountManager.masterDerivationKeyToMnemonic(algosdk.hexToBytes(args.mdk));
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({ mnemonic: mdkMnemonic }, null, 2),
                            }],
                    };
                case 'secret_key_to_mnemonic':
                    if (!args.secretKey || typeof args.secretKey !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Secret key is required');
                    }
                    const skMnemonic = AccountManager.secretKeyToMnemonic(algosdk.hexToBytes(args.secretKey));
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({ mnemonic: skMnemonic }, null, 2),
                            }],
                    };
                case 'mnemonic_to_secret_key':
                    if (!args.mnemonic || typeof args.mnemonic !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Mnemonic is required');
                    }
                    const sk = AccountManager.mnemonicToSecretKey(args.mnemonic);
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({
                                    secretKey: algosdk.bytesToHex(sk.sk),
                                    address: sk.addr.toString()
                                }, null, 2),
                            }],
                    };
                case 'seed_from_mnemonic':
                    if (!args.mnemonic || typeof args.mnemonic !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Mnemonic is required');
                    }
                    const seed = AccountManager.seedFromMnemonic(args.mnemonic);
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({ seed: algosdk.bytesToHex(seed) }, null, 2),
                            }],
                    };
                case 'mnemonic_from_seed':
                    if (!args.seed || typeof args.seed !== 'string') {
                        throw new McpError(ErrorCode.InvalidParams, 'Seed is required');
                    }
                    const seedMnemonic = AccountManager.mnemonicFromSeed(algosdk.hexToBytes(args.seed));
                    return {
                        content: [{
                                type: 'text',
                                text: JSON.stringify({ mnemonic: seedMnemonic }, null, 2),
                            }],
                    };
                default:
                    console.error(`[MCP Error] Unknown tool requested: ${name}`);
                    throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
            }
        }
        catch (error) {
            if (error instanceof McpError) {
                console.error(`[MCP Error] ${error.code}: ${error.message}`);
                throw error;
            }
            console.error('[MCP Error] Unexpected error:', error);
            throw new McpError(ErrorCode.InternalError, `Operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Creates a new account
     * @returns Object containing the address and mnemonic
     */
    static createAccount() {
        try {
            const account = algosdk.generateAccount();
            const mnemonic = algosdk.secretKeyToMnemonic(account.sk);
            return {
                address: account.addr.toString(),
                mnemonic,
            };
        }
        catch (error) {
            console.error('[MCP Error] Failed to create account:', error);
            throw new McpError(ErrorCode.InternalError, `Failed to create account: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Rekeys an account to a new address
     * @param fromAddress The address to rekey from
     * @param toAddress The address to rekey to
     * @returns The rekey transaction object
     */
    static async createRekeyTransaction(fromAddress, toAddress, network) {
        try {
            const algodClient = getAlgodClient(network);
            const suggestedParams = await algodClient.getTransactionParams().do();
            return algosdk.makePaymentTxnWithSuggestedParamsFromObject({
                sender: fromAddress,
                receiver: fromAddress,
                amount: 0,
                rekeyTo: toAddress,
                suggestedParams,
            });
        }
        catch (error) {
            console.error('[MCP Error] Failed to create rekey transaction:', error);
            throw new McpError(ErrorCode.InternalError, `Failed to create rekey transaction: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Converts a mnemonic to a master derivation key
     * @param mnemonic The mnemonic to convert
     * @returns The master derivation key
     */
    static mnemonicToMasterDerivationKey(mnemonic) {
        try {
            return algosdk.mnemonicToMasterDerivationKey(mnemonic);
        }
        catch (error) {
            console.error('[MCP Error] Failed to convert mnemonic to MDK:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid mnemonic provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Converts a master derivation key to a mnemonic
     * @param mdk The master derivation key to convert
     * @returns The mnemonic
     */
    static masterDerivationKeyToMnemonic(mdk) {
        try {
            return algosdk.masterDerivationKeyToMnemonic(mdk);
        }
        catch (error) {
            console.error('[MCP Error] Failed to convert MDK to mnemonic:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid master derivation key provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Converts a secret key to a mnemonic
     * @param secretKey The secret key to convert
     * @returns The mnemonic
     */
    static secretKeyToMnemonic(secretKey) {
        try {
            return algosdk.secretKeyToMnemonic(secretKey);
        }
        catch (error) {
            console.error('[MCP Error] Failed to convert secret key to mnemonic:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid secret key provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Converts a mnemonic to a secret key
     * @param mnemonic The mnemonic to convert
     * @returns The secret key
     */
    static mnemonicToSecretKey(mnemonic) {
        try {
            return algosdk.mnemonicToSecretKey(mnemonic);
        }
        catch (error) {
            console.error('[MCP Error] Failed to convert mnemonic to secret key:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid mnemonic provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Generates a seed from a mnemonic
     * @param mnemonic The mnemonic to generate the seed from
     * @returns The seed
     */
    static seedFromMnemonic(mnemonic) {
        try {
            return algosdk.seedFromMnemonic(mnemonic);
        }
        catch (error) {
            console.error('[MCP Error] Failed to generate seed from mnemonic:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid mnemonic provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Generates a mnemonic from a seed
     * @param seed The seed to generate the mnemonic from
     * @returns The mnemonic
     */
    static mnemonicFromSeed(seed) {
        try {
            return algosdk.mnemonicFromSeed(seed);
        }
        catch (error) {
            console.error('[MCP Error] Failed to generate mnemonic from seed:', error);
            throw new McpError(ErrorCode.InvalidParams, `Invalid seed provided: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
}
AccountManager.accountTools = [
    {
        name: 'create_account',
        description: 'Create a new Algorand account',
        inputSchema: withCommonParams(accountToolSchemas.createAccount),
    },
    {
        name: 'rekey_account',
        description: 'Rekey an Algorand account to a new address',
        inputSchema: withCommonParams(accountToolSchemas.rekeyAccount),
    },
    {
        name: 'mnemonic_to_mdk',
        description: 'Convert a mnemonic to a master derivation key',
        inputSchema: withCommonParams(accountToolSchemas.mnemonicToMdk),
    },
    {
        name: 'mdk_to_mnemonic',
        description: 'Convert a master derivation key to a mnemonic',
        inputSchema: withCommonParams(accountToolSchemas.mdkToMnemonic),
    },
    {
        name: 'secret_key_to_mnemonic',
        description: 'Convert a secret key to a mnemonic',
        inputSchema: withCommonParams(accountToolSchemas.secretKeyToMnemonic),
    },
    {
        name: 'mnemonic_to_secret_key',
        description: 'Convert a mnemonic to a secret key',
        inputSchema: withCommonParams(accountToolSchemas.mnemonicToSecretKey),
    },
    {
        name: 'seed_from_mnemonic',
        description: 'Generate a seed from a mnemonic',
        inputSchema: withCommonParams(accountToolSchemas.seedFromMnemonic),
    },
    {
        name: 'mnemonic_from_seed',
        description: 'Generate a mnemonic from a seed',
        inputSchema: withCommonParams(accountToolSchemas.mnemonicFromSeed),
    }
];
