import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AddLiquidity, poolUtils } from '@tinymanorg/tinyman-js-sdk';
import { getAlgodClient, extractNetwork } from '../../../algorand-client.js';
import { withCommonParams } from '../../commonParams.js';
export const liquidityTools = [
    {
        name: 'api_tinyman_get_liquidity_quote',
        description: 'Get quote for adding liquidity to a pool',
        inputSchema: withCommonParams({
            type: 'object',
            properties: {
                asset1Id: {
                    type: 'integer',
                    description: 'ID of the first asset'
                },
                asset2Id: {
                    type: 'integer',
                    description: 'ID of the second asset'
                },
                asset1Amount: {
                    type: 'integer',
                    description: 'Amount of first asset to add'
                },
                asset2Amount: {
                    type: 'integer',
                    description: 'Amount of second asset to add'
                },
                mode: {
                    type: 'string',
                    enum: ['initial', 'flexible', 'singleAsset'],
                    description: 'Mode of adding liquidity'
                },
                version: {
                    type: 'string',
                    enum: ['v1_1', 'v2'],
                    description: 'Tinyman protocol version',
                    default: 'v2'
                }
            },
            required: ['asset1Id', 'asset2Id', 'mode']
        })
    }
];
export async function handleLiquidityTools(args) {
    const { name, asset1Id, asset2Id, asset1Amount = 0, asset2Amount = 0, mode, version = 'v2' } = args;
    const network = extractNetwork(args);
    const algodClient = getAlgodClient(network);
    if (network === 'localnet') {
        throw new McpError(ErrorCode.InvalidRequest, 'Tinyman is not available on localnet');
    }
    const tinymanNetwork = network;
    async function getAssetDecimals(assetId) {
        try {
            if (assetId === 0)
                return 6; // Algo has 6 decimals
            const assetInfo = await algodClient.getAssetByID(assetId).do();
            return assetInfo.params.decimals;
        }
        catch (error) {
            console.error(`Failed to get decimals for asset ${assetId}:`, error);
            return 6; // Default to 6 decimals if we can't get the info
        }
    }
    if (name === 'api_tinyman_get_liquidity_quote') {
        try {
            // Get pool information first
            const poolInfo = await (version === 'v2'
                ? poolUtils.v2.getPoolInfo({
                    client: algodClient,
                    network: tinymanNetwork,
                    asset1ID: asset1Id,
                    asset2ID: asset2Id
                })
                : poolUtils.v1_1.getPoolInfo({
                    client: algodClient,
                    network: tinymanNetwork,
                    asset1ID: asset1Id,
                    asset2ID: asset2Id
                }));
            let quote;
            if (version === 'v2') {
                switch (mode) {
                    case 'initial':
                        quote = AddLiquidity.v2.initial.getQuote({
                            pool: poolInfo,
                            asset1: {
                                amount: BigInt(asset1Amount),
                                decimals: await getAssetDecimals(asset1Id)
                            },
                            asset2: {
                                amount: BigInt(asset2Amount),
                                decimals: await getAssetDecimals(asset2Id)
                            }
                        });
                        break;
                    case 'flexible':
                        quote = AddLiquidity.v2.flexible.getQuote({
                            pool: poolInfo,
                            asset1: {
                                amount: BigInt(asset1Amount),
                                decimals: await getAssetDecimals(asset1Id)
                            },
                            asset2: {
                                amount: BigInt(asset2Amount),
                                decimals: await getAssetDecimals(asset2Id)
                            }
                        });
                        break;
                    case 'singleAsset':
                        quote = AddLiquidity.v2.withSingleAsset.getQuote({
                            pool: poolInfo,
                            assetIn: {
                                id: asset1Id,
                                amount: BigInt(asset1Amount)
                            },
                            decimals: {
                                asset1: await getAssetDecimals(asset1Id),
                                asset2: await getAssetDecimals(asset2Id)
                            }
                        });
                        break;
                    default:
                        throw new McpError(ErrorCode.InvalidParams, `Invalid liquidity mode: ${mode}`);
                }
            }
            else {
                // Get pool reserves for v1.1
                const reserves = await poolUtils.v1_1.getPoolReserves(algodClient, poolInfo);
                quote = AddLiquidity.v1_1.getQuote({
                    pool: poolInfo,
                    reserves,
                    asset1In: BigInt(asset1Amount),
                    asset2In: BigInt(asset2Amount)
                });
            }
            return quote;
        }
        catch (error) {
            throw new McpError(ErrorCode.InternalError, `Failed to get liquidity quote: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    throw new McpError(ErrorCode.MethodNotFound, `Unknown liquidity tool: ${name}`);
}
