import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { getIndexerClient, extractNetwork } from '../../../algorand-client.js';
import { ResponseProcessor } from '../../../utils/responseProcessor.js';
import { withCommonParams } from '../../commonParams.js';
export const transactionTools = [
    {
        name: 'api_indexer_lookup_transaction_by_id',
        description: 'Get transaction information by ID',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                txId: {
                    type: 'string',
                    description: 'Transaction ID'
                }
            },
            required: ['txId']
        })
    },
    {
        name: 'api_indexer_lookup_account_transactions',
        description: 'Get account transaction history',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                address: {
                    type: 'string',
                    description: 'Account address'
                },
                limit: {
                    type: 'integer',
                    description: 'Maximum number of transactions to return'
                },
                beforeTime: {
                    type: 'string',
                    description: 'Only return transactions before this time'
                },
                afterTime: {
                    type: 'string',
                    description: 'Only return transactions after this time'
                },
                minRound: {
                    type: 'integer',
                    description: 'Only return transactions after this round'
                },
                maxRound: {
                    type: 'integer',
                    description: 'Only return transactions before this round'
                },
                txType: {
                    type: 'string',
                    description: 'Filter by transaction type'
                },
                assetId: {
                    type: 'integer',
                    description: 'Filter by asset ID'
                }
            },
            required: ['address']
        })
    },
    {
        name: 'api_indexer_search_for_transactions',
        description: 'Search for transactions with various criteria',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                limit: {
                    type: 'integer',
                    description: 'Maximum number of transactions to return'
                },
                beforeTime: {
                    type: 'string',
                    description: 'Only return transactions before this time'
                },
                afterTime: {
                    type: 'string',
                    description: 'Only return transactions after this time'
                },
                minRound: {
                    type: 'integer',
                    description: 'Only return transactions after this round'
                },
                maxRound: {
                    type: 'integer',
                    description: 'Only return transactions before this round'
                },
                address: {
                    type: 'string',
                    description: 'Filter by account address'
                },
                addressRole: {
                    type: 'string',
                    description: 'Filter by address role (sender or receiver)'
                },
                txType: {
                    type: 'string',
                    description: 'Filter by transaction type'
                },
                assetId: {
                    type: 'integer',
                    description: 'Filter by asset ID'
                },
                applicationId: {
                    type: 'integer',
                    description: 'Filter by application ID'
                },
                currencyGreaterThan: {
                    type: 'integer',
                    description: 'Filter by minimum amount'
                },
                currencyLessThan: {
                    type: 'integer',
                    description: 'Filter by maximum amount'
                },
                round: {
                    type: 'integer',
                    description: 'Filter by specific round'
                },
                nextToken: {
                    type: 'string',
                    description: 'Token for retrieving the next page of results'
                }
            }
        })
    }
];
export async function lookupTransactionByID(txId, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error(`Looking up transaction with ID ${txId}`);
        const response = await indexerClient.lookupTransactionByID(txId).do();
        // Log only metadata instead of full response
        console.error('Transaction response metadata:', {
            currentRound: response.currentRound,
            transaction: response.transaction ? 'present' : 'not found'
        });
        return response;
    }
    catch (error) {
        console.error('Transaction lookup error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to get transaction: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export async function lookupAccountTransactions(address, params, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error(`Looking up transactions for account ${address}`);
        let search = indexerClient.lookupAccountTransactions(address);
        if (params?.limit) {
            search = search.limit(params.limit);
        }
        if (params?.beforeTime) {
            search = search.beforeTime(params.beforeTime);
        }
        if (params?.afterTime) {
            search = search.afterTime(params.afterTime);
        }
        if (params?.minRound) {
            search = search.minRound(params.minRound);
        }
        if (params?.maxRound) {
            search = search.maxRound(params.maxRound);
        }
        if (params?.txType) {
            search = search.txType(params.txType);
        }
        if (params?.assetId) {
            search = search.assetID(params.assetId);
        }
        const response = await search.do();
        // Log only metadata instead of full response
        console.error('Account transactions response metadata:', {
            currentRound: response.currentRound,
            nextToken: response.nextToken,
            transactionCount: response.transactions?.length || 0
        });
        return response;
    }
    catch (error) {
        console.error('Account transactions lookup error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to get account transactions: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export async function searchForTransactions(params, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error('Searching transactions with params:', params);
        let search = indexerClient.searchForTransactions();
        if (params?.limit) {
            search = search.limit(params.limit);
        }
        if (params?.beforeTime) {
            search = search.beforeTime(params.beforeTime);
        }
        if (params?.afterTime) {
            search = search.afterTime(params.afterTime);
        }
        if (params?.minRound) {
            search = search.minRound(params.minRound);
        }
        if (params?.maxRound) {
            search = search.maxRound(params.maxRound);
        }
        if (params?.address) {
            search = search.address(params.address);
        }
        if (params?.addressRole) {
            search = search.addressRole(params.addressRole);
        }
        if (params?.txType) {
            search = search.txType(params.txType);
        }
        if (params?.assetId) {
            search = search.assetID(params.assetId);
        }
        if (params?.applicationId) {
            search = search.applicationID(params.applicationId);
        }
        if (params?.currencyGreaterThan) {
            search = search.currencyGreaterThan(params.currencyGreaterThan);
        }
        if (params?.currencyLessThan) {
            search = search.currencyLessThan(params.currencyLessThan);
        }
        if (params?.round) {
            search = search.round(params.round);
        }
        if (params?.nextToken) {
            search = search.nextToken(params.nextToken);
        }
        const response = await search.do();
        // Log only metadata instead of full response
        console.error('Search transactions response metadata:', {
            currentRound: response.currentRound,
            nextToken: response.nextToken,
            transactionCount: response.transactions?.length || 0
        });
        return response;
    }
    catch (error) {
        console.error('Search transactions error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to search transactions: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export const handleTransactionTools = ResponseProcessor.wrapResourceHandler(async function handleTransactionTools(args) {
    const name = args.name;
    const network = extractNetwork(args);
    switch (name) {
        case 'api_indexer_lookup_transaction_by_id': {
            const { txId } = args;
            const info = await lookupTransactionByID(txId, network);
            return info.transaction;
        }
        case 'api_indexer_lookup_account_transactions': {
            const { address, ...params } = args;
            const info = await lookupAccountTransactions(address, params, network);
            return info.transactions;
        }
        case 'api_indexer_search_for_transactions': {
            const info = await searchForTransactions(args, network);
            return info.transactions;
        }
        default:
            throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
    }
});
