/**
 * Binance Order Management Tools
 *
 * - binance_create_order: Create a new order (HIGH RISK)
 * - binance_cancel_order: Cancel a pending order
 *
 * @version 1.0.0
 * @author Trading Platform Trading Platform
 */

import { z } from 'zod';
import { getBinanceClient, BinanceOrder, CreateOrderParams } from '../services/binance-client';
import { performRiskCheck, recordTradeVolume } from '../middleware/risk-check';
import { logger } from '../utils/logger';

// ==========================================
// binance_create_order
// ==========================================

/**
 * Tool: binance_create_order
 * Create a new buy or sell order
 * HIGH RISK - Requires confirmation
 */
export const binanceCreateOrderSchema = {
  name: 'binance_create_order',
  description: 'Create a new buy or sell order on Binance. HIGH RISK - Ensure you validate with the user before executing.',
  inputSchema: {
    type: 'object' as const,
    properties: {
      symbol: {
        type: 'string',
        description: 'Trading pair symbol (e.g., BTCUSDT, ETHUSDT)',
      },
      side: {
        type: 'string',
        enum: ['buy', 'sell'],
        description: 'Order direction: buy or sell',
      },
      type: {
        type: 'string',
        enum: ['market', 'limit', 'stop_loss', 'take_profit'],
        description: 'Order type. Default: market',
      },
      amount: {
        type: 'number',
        description: 'Amount of the base asset to buy/sell',
      },
      price: {
        type: 'number',
        description: 'Price per unit (required for limit orders)',
      },
      stopPrice: {
        type: 'number',
        description: 'Stop price (required for stop_loss and take_profit orders)',
      },
    },
    required: ['symbol', 'side', 'amount'] as string[],
  },
  riskLevel: 'HIGH',
  requiresConfirmation: true,
};

export const BinanceCreateOrderInputSchema = z.object({
  symbol: z.string().min(1).max(20).transform((s) => s.toUpperCase()),
  side: z.enum(['buy', 'sell']),
  type: z.enum(['market', 'limit', 'stop_loss', 'take_profit']).default('market'),
  amount: z.number().positive(),
  price: z.number().positive().optional(),
  stopPrice: z.number().positive().optional(),
});

export type BinanceCreateOrderInput = z.infer<typeof BinanceCreateOrderInputSchema>;

export interface BinanceCreateOrderResult {
  success: boolean;
  data?: {
    order: BinanceOrder;
    riskWarnings?: string[];
  };
  error?: string;
  riskCheckFailed?: boolean;
}

export async function binance_create_order(
  params: BinanceCreateOrderInput
): Promise<BinanceCreateOrderResult> {
  try {
    const client = getBinanceClient();

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

    // 1. Perform risk check
    const riskCheck = await performRiskCheck({
      symbol: params.symbol,
      side: params.side,
      amount: params.amount,
      price: params.price,
    });

    if (!riskCheck.allowed) {
      logger.warn('Order rejected by risk check', {
        params,
        reason: riskCheck.reason,
      });
      return {
        success: false,
        error: riskCheck.reason,
        riskCheckFailed: true,
      };
    }

    // 2. Validate order parameters
    if (params.type === 'limit' && !params.price) {
      return {
        success: false,
        error: 'Price is required for limit orders',
      };
    }

    if ((params.type === 'stop_loss' || params.type === 'take_profit') && !params.stopPrice) {
      return {
        success: false,
        error: `Stop price is required for ${params.type} orders`,
      };
    }

    // 3. Create the order
    const orderParams: CreateOrderParams = {
      symbol: params.symbol,
      side: params.side,
      type: params.type,
      amount: params.amount,
      price: params.price,
      stopPrice: params.stopPrice,
    };

    const result = await client.createOrder(orderParams);

    if (result.success && result.order) {
      // Record trade volume for daily limit tracking
      if (riskCheck.orderValue) {
        recordTradeVolume(riskCheck.orderValue);
      }

      logger.info('Order created successfully', {
        orderId: result.order.id,
        symbol: params.symbol,
        side: params.side,
        amount: params.amount,
      });

      return {
        success: true,
        data: {
          order: result.order,
          riskWarnings: riskCheck.warnings,
        },
      };
    }

    return {
      success: false,
      error: result.error || 'Failed to create order',
    };
  } catch (error) {
    logger.error('Order creation failed', { error, params });
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error occurred',
    };
  }
}

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

  if (result.success && result.data) {
    const o = result.data.order;
    const priceStr = o.price ? `$${o.price.toFixed(8)}` : 'MARKET';

    let warningsStr = '';
    if (result.data.riskWarnings && result.data.riskWarnings.length > 0) {
      warningsStr = `\n\nWarnings:\n${result.data.riskWarnings.map((w) => `  - ${w}`).join('\n')}`;
    }

    const formattedOutput = `
Order Created Successfully
${'='.repeat(35)}
Order ID: ${o.id}
Symbol: ${o.symbol}
Side: ${o.side.toUpperCase()}
Type: ${o.type.toUpperCase()}
Price: ${priceStr}
Amount: ${o.amount.toFixed(8)}
Filled: ${o.filled.toFixed(8)}
Status: ${o.status}
Created: ${new Date(o.createdAt).toISOString()}${warningsStr}
`.trim();

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

  const errorPrefix = result.riskCheckFailed ? 'Risk Check Failed: ' : 'Error: ';
  return {
    content: [{ type: 'text', text: `${errorPrefix}${result.error}` }],
  };
}

// ==========================================
// binance_cancel_order
// ==========================================

/**
 * Tool: binance_cancel_order
 * Cancel a pending order
 */
export const binanceCancelOrderSchema = {
  name: 'binance_cancel_order',
  description: 'Cancel a pending order by order ID and symbol',
  inputSchema: {
    type: 'object' as const,
    properties: {
      symbol: {
        type: 'string',
        description: 'Trading pair symbol (e.g., BTCUSDT)',
      },
      orderId: {
        type: 'string',
        description: 'Order ID to cancel',
      },
    },
    required: ['symbol', 'orderId'] as string[],
  },
  riskLevel: 'MEDIUM',
};

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

export type BinanceCancelOrderInput = z.infer<typeof BinanceCancelOrderInputSchema>;

export interface BinanceCancelOrderResult {
  success: boolean;
  data?: {
    cancelledOrder: BinanceOrder;
  };
  error?: string;
}

export async function binance_cancel_order(
  params: BinanceCancelOrderInput
): Promise<BinanceCancelOrderResult> {
  try {
    const client = getBinanceClient();

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

    const result = await client.cancelOrder(params.orderId, params.symbol);

    if (result.success && result.order) {
      logger.info('Order cancelled successfully', {
        orderId: params.orderId,
        symbol: params.symbol,
      });

      return {
        success: true,
        data: {
          cancelledOrder: result.order,
        },
      };
    }

    return {
      success: false,
      error: result.error || 'Failed to cancel order',
    };
  } catch (error) {
    logger.error('Order cancellation failed', { error, params });
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error occurred',
    };
  }
}

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

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

    const formattedOutput = `
Order Cancelled Successfully
${'='.repeat(35)}
Order ID: ${o.id}
Symbol: ${o.symbol}
Side: ${o.side.toUpperCase()}
Type: ${o.type.toUpperCase()}
Original Amount: ${o.amount.toFixed(8)}
Filled Before Cancel: ${o.filled.toFixed(8)}
Status: ${o.status}
`.trim();

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

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