/**
 * Binance Account Tools
 *
 * - binance_get_account: Get account balance and status
 * - binance_get_open_orders: Get all open orders
 *
 * @version 1.0.0
 * @author Trading Platform Trading Platform
 */

import { z } from 'zod';
import { getBinanceClient, BinanceAccount, BinanceOrder } from '../services/binance-client';

// ==========================================
// binance_get_account
// ==========================================

/**
 * Tool: binance_get_account
 * Get account balance and status
 */
export const binanceGetAccountSchema = {
  name: 'binance_get_account',
  description: 'Get Binance account balance and status. Shows all assets with non-zero balance.',
  inputSchema: {
    type: 'object' as const,
    properties: {},
    required: [] as string[],
  },
};

export const BinanceGetAccountInputSchema = z.object({});

export type BinanceGetAccountInput = z.infer<typeof BinanceGetAccountInputSchema>;

export interface BinanceGetAccountResult {
  success: boolean;
  data?: BinanceAccount & { totalUsdtEstimate?: number };
  error?: string;
}

export async function binance_get_account(
  _params: BinanceGetAccountInput
): Promise<BinanceGetAccountResult> {
  try {
    const client = getBinanceClient();

    if (!client.isConfigured()) {
      return {
        success: false,
        error: 'Binance API keys are not configured',
      };
    }

    const connected = await client.isConnected();
    if (!connected) {
      return {
        success: false,
        error: 'Cannot connect to Binance. Please check your network.',
      };
    }

    const account = await client.getAccount();

    // Estimate total value in USDT
    let totalUsdtEstimate = 0;
    for (const balance of account.balances) {
      if (balance.asset === 'USDT' || balance.asset === 'BUSD' || balance.asset === 'USDC') {
        totalUsdtEstimate += balance.total;
      } else if (balance.total > 0) {
        try {
          const price = await client.getCurrentPrice(`${balance.asset}USDT`);
          totalUsdtEstimate += balance.total * price;
        } catch {
          // Skip if no USDT pair exists
        }
      }
    }

    return {
      success: true,
      data: {
        ...account,
        totalUsdtEstimate,
      },
    };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error occurred',
    };
  }
}

export async function handleBinanceGetAccount(
  params: unknown
): Promise<{ content: Array<{ type: string; text: string }> }> {
  const validatedParams = BinanceGetAccountInputSchema.parse(params);
  const result = await binance_get_account(validatedParams);

  if (result.success && result.data) {
    const d = result.data;

    // Sort balances by total value
    const sortedBalances = [...d.balances].sort((a, b) => {
      // USDT first, then by total
      if (a.asset === 'USDT') return -1;
      if (b.asset === 'USDT') return 1;
      return b.total - a.total;
    });

    let balancesStr = sortedBalances
      .slice(0, 20) // Top 20 assets
      .map((b) => {
        const lockedStr = b.locked > 0 ? ` (Locked: ${b.locked.toFixed(8)})` : '';
        return `  ${b.asset.padEnd(8)} Free: ${b.free.toFixed(8)}${lockedStr}`;
      })
      .join('\n');

    const formattedOutput = `
Binance Account Information
${'='.repeat(35)}
Account Type: ${d.accountType}
Can Trade: ${d.canTrade ? 'Yes' : 'No'}
Can Withdraw: ${d.canWithdraw ? 'Yes' : 'No'}

Estimated Total Value
---------------------
~$${d.totalUsdtEstimate?.toFixed(2) ?? 'N/A'} USDT

Asset Balances (${d.balances.length} with balance)
${'='.repeat(35)}
${balancesStr}
${d.balances.length > 20 ? `\n  ... and ${d.balances.length - 20} more assets` : ''}

Last Update: ${new Date(d.updateTime).toISOString()}
`.trim();

    return {
      content: [{ type: 'text', text: formattedOutput }],
    };
  }

  return {
    content: [{ type: 'text', text: `Error: ${result.error}` }],
  };
}

// ==========================================
// binance_get_open_orders
// ==========================================

/**
 * Tool: binance_get_open_orders
 * Get all open (pending) orders
 */
export const binanceGetOpenOrdersSchema = {
  name: 'binance_get_open_orders',
  description: 'Get all open (pending) orders. Optionally filter by symbol.',
  inputSchema: {
    type: 'object' as const,
    properties: {
      symbol: {
        type: 'string',
        description: 'Optional: Filter by trading pair symbol (e.g., BTCUSDT)',
      },
    },
    required: [] as string[],
  },
};

export const BinanceGetOpenOrdersInputSchema = z.object({
  symbol: z.string().min(1).max(20).transform((s) => s.toUpperCase()).optional(),
});

export type BinanceGetOpenOrdersInput = z.infer<typeof BinanceGetOpenOrdersInputSchema>;

export interface BinanceGetOpenOrdersResult {
  success: boolean;
  data?: {
    orders: BinanceOrder[];
    count: number;
  };
  error?: string;
}

export async function binance_get_open_orders(
  params: BinanceGetOpenOrdersInput
): Promise<BinanceGetOpenOrdersResult> {
  try {
    const client = getBinanceClient();

    if (!client.isConfigured()) {
      return {
        success: false,
        error: 'Binance API keys are not configured',
      };
    }

    const orders = await client.getOpenOrders(params.symbol);

    return {
      success: true,
      data: {
        orders,
        count: orders.length,
      },
    };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error occurred',
    };
  }
}

export async function handleBinanceGetOpenOrders(
  params: unknown
): Promise<{ content: Array<{ type: string; text: string }> }> {
  const validatedParams = BinanceGetOpenOrdersInputSchema.parse(params);
  const result = await binance_get_open_orders(validatedParams);

  if (result.success && result.data) {
    const d = result.data;

    if (d.count === 0) {
      return {
        content: [
          {
            type: 'text',
            text: `No open orders${validatedParams.symbol ? ` for ${validatedParams.symbol}` : ''}`,
          },
        ],
      };
    }

    let ordersStr = d.orders
      .map((o) => {
        const priceStr = o.price ? `$${o.price.toFixed(8)}` : 'MARKET';
        const filledPct = o.amount > 0 ? ((o.filled / o.amount) * 100).toFixed(1) : '0';
        return `  #${o.id}
    Symbol: ${o.symbol} | ${o.side.toUpperCase()} | ${o.type.toUpperCase()}
    Price: ${priceStr} | Amount: ${o.amount.toFixed(8)}
    Filled: ${o.filled.toFixed(8)} (${filledPct}%) | Remaining: ${o.remaining.toFixed(8)}
    Status: ${o.status} | Created: ${new Date(o.createdAt).toISOString()}`;
      })
      .join('\n\n');

    const formattedOutput = `
Open Orders${validatedParams.symbol ? ` - ${validatedParams.symbol}` : ''}
${'='.repeat(35)}
Total Orders: ${d.count}

${ordersStr}
`.trim();

    return {
      content: [{ type: 'text', text: formattedOutput }],
    };
  }

  return {
    content: [{ type: 'text', text: `Error: ${result.error}` }],
  };
}
