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 assetTools = [
    {
        name: 'api_indexer_lookup_asset_by_id',
        description: 'Get asset information and configuration',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                assetId: {
                    type: 'integer',
                    description: 'Asset ID'
                }
            },
            required: ['assetId']
        })
    },
    {
        name: 'api_indexer_lookup_asset_balances',
        description: 'Get accounts holding this asset and their balances',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                assetId: {
                    type: 'integer',
                    description: 'Asset ID'
                },
                limit: {
                    type: 'integer',
                    description: 'Maximum number of balances to return'
                },
                currencyGreaterThan: {
                    type: 'integer',
                    description: 'Filter by minimum balance'
                },
                currencyLessThan: {
                    type: 'integer',
                    description: 'Filter by maximum balance'
                },
                nextToken: {
                    type: 'string',
                    description: 'Token for retrieving the next page of results'
                },
                address: {
                    type: 'string',
                    description: 'Filter by account address'
                }
            },
            required: ['assetId']
        })
    },
    {
        name: 'api_indexer_lookup_asset_transactions',
        description: 'Get transactions involving this asset',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                assetId: {
                    type: 'integer',
                    description: 'Asset ID'
                },
                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)'
                },
                excludeCloseTo: {
                    type: 'boolean',
                    description: 'Whether to exclude close-to transactions'
                },
                nextToken: {
                    type: 'string',
                    description: 'Token for retrieving the next page of results'
                },
                txid: {
                    type: 'string',
                    description: 'Filter by transaction ID'
                }
            },
            required: ['assetId']
        })
    },
    {
        name: 'api_indexer_search_for_assets',
        description: 'Search for assets with various criteria',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                limit: {
                    type: 'integer',
                    description: 'Maximum number of assets to return'
                },
                creator: {
                    type: 'string',
                    description: 'Filter by creator address'
                },
                name: {
                    type: 'string',
                    description: 'Filter by asset name'
                },
                unit: {
                    type: 'string',
                    description: 'Filter by asset unit name'
                },
                assetId: {
                    type: 'integer',
                    description: 'Filter by asset ID'
                },
                nextToken: {
                    type: 'string',
                    description: 'Token for retrieving the next page of results'
                }
            }
        })
    }
];
export async function lookupAssetByID(assetId, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error(`Looking up asset info for ID ${assetId}`);
        const response = await indexerClient.lookupAssetByID(assetId).do();
        console.error('Asset response:', JSON.stringify(response, null, 2));
        return response;
    }
    catch (error) {
        console.error('Asset lookup error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to get asset info: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export async function lookupAssetBalances(assetId, params, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error(`Looking up balances for asset ${assetId}`);
        let search = indexerClient.lookupAssetBalances(assetId);
        if (params?.limit) {
            search = search.limit(params.limit);
        }
        if (params?.currencyGreaterThan) {
            search = search.currencyGreaterThan(params.currencyGreaterThan);
        }
        if (params?.currencyLessThan) {
            search = search.currencyLessThan(params.currencyLessThan);
        }
        if (params?.nextToken) {
            search = search.nextToken(params.nextToken);
        }
        const response = await search.do();
        console.error('Asset balances response:', JSON.stringify(response, null, 2));
        return response;
    }
    catch (error) {
        console.error('Asset balances lookup error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to get asset balances: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export async function lookupAssetTransactions(assetId, params, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error(`Looking up transactions for asset ${assetId}`);
        let search = indexerClient.lookupAssetTransactions(assetId);
        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?.excludeCloseTo) {
            search = search.excludeCloseTo(params.excludeCloseTo);
        }
        if (params?.nextToken) {
            search = search.nextToken(params.nextToken);
        }
        const response = await search.do();
        console.error('Asset transactions response:', JSON.stringify(response, null, 2));
        return response;
    }
    catch (error) {
        console.error('Asset transactions lookup error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to get asset transactions: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export async function searchForAssets(params, network = 'mainnet') {
    try {
        const indexerClient = getIndexerClient(network);
        console.error('Searching assets with params:', params);
        let search = indexerClient.searchForAssets();
        if (params?.limit) {
            search = search.limit(params.limit);
        }
        if (params?.creator) {
            search = search.creator(params.creator);
        }
        if (params?.name) {
            search = search.name(params.name);
        }
        if (params?.unit) {
            search = search.unit(params.unit);
        }
        if (params?.assetId) {
            search = search.index(params.assetId);
        }
        if (params?.nextToken) {
            search = search.nextToken(params.nextToken);
        }
        const response = await search.do();
        console.error('Search assets response:', JSON.stringify(response, null, 2));
        return response;
    }
    catch (error) {
        console.error('Search assets error:', error);
        if (error instanceof McpError) {
            throw error;
        }
        throw new McpError(ErrorCode.InternalError, `Failed to search assets: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export const handleAssetTools = ResponseProcessor.wrapResourceHandler(async function handleAssetTools(args) {
    const name = args.name;
    const network = extractNetwork(args);
    switch (name) {
        case 'api_indexer_lookup_asset_by_id': {
            const { assetId } = args;
            const info = await lookupAssetByID(assetId, network);
            return info.asset;
        }
        case 'api_indexer_lookup_asset_balances': {
            const { assetId, ...params } = args;
            const balances = await lookupAssetBalances(assetId, params, network);
            return balances.balances;
        }
        case 'api_indexer_lookup_asset_transactions': {
            const { assetId, ...params } = args;
            const transactions = await lookupAssetTransactions(assetId, params, network);
            return transactions.transactions;
        }
        case 'api_indexer_search_for_assets': {
            const assets = await searchForAssets(args, network);
            return assets.assets;
        }
        default:
            throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
    }
});
