/**
 * MT4 Position Tools
 *
 * - mt4_get_positions: List all open positions
 * - mt4_close_position: Close a specific position
 */

import { z } from 'zod';
import { getMT4Client, MT4Position, TradeResult } from '../services/mt4-client';

// ==========================================
// mt4_get_positions
// ==========================================

/**
 * mt4_get_positions - List all open positions
 *
 * @description Retrieves all currently open positions from MT4 terminal.
 * Can optionally filter by symbol.
 *
 * @param symbol - Optional symbol to filter positions (e.g., "XAUUSD")
 * @returns Array of open positions with details
 *
 * @example
 * const result = await mt4_get_positions({});
 * // Returns all positions
 *
 * const result = await mt4_get_positions({ symbol: "XAUUSD" });
 * // Returns only XAUUSD positions
 */

export const mt4GetPositionsSchema = {
  name: 'mt4_get_positions',
  description: 'List all open trading positions from MT4. Optionally filter by symbol.',
  inputSchema: {
    type: 'object' as const,
    properties: {
      symbol: {
        type: 'string',
        description: 'Optional: Filter positions by symbol (e.g., XAUUSD, EURUSD)',
      },
    },
    required: [] as string[],
  },
};

export const Mt4GetPositionsInputSchema = z.object({
  symbol: z.string().optional(),
});

export type Mt4GetPositionsInput = z.infer<typeof Mt4GetPositionsInputSchema>;

export interface Mt4GetPositionsResult {
  success: boolean;
  data?: {
    positions: MT4Position[];
    totalProfit: number;
    count: number;
  };
  error?: string;
}

export async function mt4_get_positions(
  params: Mt4GetPositionsInput
): Promise<Mt4GetPositionsResult> {
  try {
    const client = getMT4Client();

    // Check connection
    const isConnected = await client.isConnected();
    if (!isConnected) {
      return {
        success: false,
        error: 'MT4 terminal is not connected',
      };
    }

    // Get all positions
    let positions = await client.getPositions();

    // Filter by symbol if specified
    if (params.symbol) {
      positions = positions.filter(
        p => p.symbol.toUpperCase() === params.symbol!.toUpperCase()
      );
    }

    // Calculate total profit
    const totalProfit = positions.reduce((sum, p) => sum + p.profit, 0);

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

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

  if (result.success && result.data) {
    if (result.data.count === 0) {
      return {
        content: [
          {
            type: 'text',
            text: params && (params as Mt4GetPositionsInput).symbol
              ? `No open positions found for ${(params as Mt4GetPositionsInput).symbol}`
              : 'No open positions found',
          },
        ],
      };
    }

    const positionLines = result.data.positions.map(p => {
      const direction = p.type.toUpperCase();
      const profitSign = p.profit >= 0 ? '+' : '';
      const slInfo = p.stopLoss !== null ? `SL: ${p.stopLoss}` : 'SL: None';
      const tpInfo = p.takeProfit !== null ? `TP: ${p.takeProfit}` : 'TP: None';

      return `
#${p.ticket} | ${p.symbol} | ${direction} ${p.lots} lots
  Open: ${p.openPrice} | Current: ${p.currentPrice}
  ${slInfo} | ${tpInfo}
  P/L: ${profitSign}${p.profit.toFixed(2)} | Swap: ${p.swap.toFixed(2)}
  Opened: ${p.openTime}
  Magic: ${p.magic} | Comment: ${p.comment || 'None'}`;
    });

    const formattedOutput = `
Open Positions (${result.data.count})
${'='.repeat(30)}
${positionLines.join('\n---\n')}

Total P/L: ${result.data.totalProfit >= 0 ? '+' : ''}${result.data.totalProfit.toFixed(2)}
`.trim();

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

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

// ==========================================
// mt4_close_position
// ==========================================

/**
 * mt4_close_position - Close a trading position
 *
 * @description Closes an open position by ticket number.
 * Can optionally close partial volume.
 *
 * @param ticket - Position ticket number to close
 * @param lots - Optional: Partial volume to close (default: close all)
 * @param slippage - Optional: Maximum slippage in points (default: 3)
 * @returns Trade result with success status
 *
 * @example
 * // Close entire position
 * const result = await mt4_close_position({ ticket: 123456 });
 *
 * // Close partial position
 * const result = await mt4_close_position({ ticket: 123456, lots: 0.5 });
 */

export const mt4ClosePositionSchema = {
  name: 'mt4_close_position',
  description: 'Close an open trading position by ticket number. Can close partially.',
  inputSchema: {
    type: 'object' as const,
    properties: {
      ticket: {
        type: 'number',
        description: 'Position ticket number to close',
      },
      lots: {
        type: 'number',
        description: 'Optional: Partial volume to close. If not specified, closes entire position.',
      },
      slippage: {
        type: 'number',
        description: 'Optional: Maximum slippage in points (default: 3)',
      },
    },
    required: ['ticket'] as string[],
  },
};

export const Mt4ClosePositionInputSchema = z.object({
  ticket: z.number().int().positive(),
  lots: z.number().positive().optional(),
  slippage: z.number().int().min(0).max(100).optional(),
});

export type Mt4ClosePositionInput = z.infer<typeof Mt4ClosePositionInputSchema>;

export interface Mt4ClosePositionResult {
  success: boolean;
  data?: TradeResult;
  error?: string;
}

export async function mt4_close_position(
  params: Mt4ClosePositionInput
): Promise<Mt4ClosePositionResult> {
  try {
    const client = getMT4Client();

    // Check connection
    const isConnected = await client.isConnected();
    if (!isConnected) {
      return {
        success: false,
        error: 'MT4 terminal is not connected',
      };
    }

    // Verify position exists
    const position = await client.getPosition(params.ticket);
    if (!position) {
      return {
        success: false,
        error: `Position with ticket ${params.ticket} not found`,
      };
    }

    // Validate lots if specified
    if (params.lots !== undefined && params.lots > position.lots) {
      return {
        success: false,
        error: `Requested lots (${params.lots}) exceeds position size (${position.lots})`,
      };
    }

    // Close position
    const result = await client.closePosition({
      ticket: params.ticket,
      lots: params.lots,
      slippage: params.slippage,
    });

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

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

  if (result.success && result.data) {
    const formattedOutput = `
Position Closed Successfully
============================
Ticket: ${validatedParams.ticket}
${validatedParams.lots ? `Closed Volume: ${validatedParams.lots} lots` : 'Closed: Entire position'}
Message: ${result.data.message || 'Position closed'}
`.trim();

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

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