#!/usr/bin/env python3
"""
Скрипт для управления существующими сделками: отмена, модификация, закрытие.

Использование:
    python src/manage_trade.py --list                          # Показать все открытые сделки
    python src/manage_trade.py --list --ticker SBER           # Показать сделки по SBER
    python src/manage_trade.py --cancel --trade-id <id>       # Отменить сделку
    python src/manage_trade.py --close --trade-id <id>        # Закрыть сделку по рыночной цене
    python src/manage_trade.py --modify-sl --trade-id <id> --new-sl 95.0  # Изменить SL
    python src/manage_trade.py --modify-tp --trade-id <id> --new-tp 110.0 # Изменить TP

Функции:
    - Просмотр открытых сделок
    - Отмена сделки (отмена всех ордеров)
    - Закрытие сделки (рыночный выход)
    - Модификация SL/TP
    - Мониторинг сделок
"""

import argparse
import json
import os
import sys
from datetime import datetime

# Добавляем корень проекта в sys.path
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, PROJECT_ROOT)

from src.api.tbank import set_tbank_env, get_orders, cancel_order, get_current_candle
from src.api.trade_journal import journal
from src.utils.config import config


def format_currency(amount: float, currency: str = "RUB") -> str:
    """Форматирование суммы с валютой."""
    if currency == "RUB":
        return f"{amount:,.2f} ₽"
    else:
        return f"{amount:,.2f} {currency}"


def list_open_trades(ticker: str = None) -> list:
    """Показать все открытые сделки."""
    print("📋 Открытые сделки:")
    
    open_trades = journal.get_open_trades()
    if ticker:
        open_trades = [t for t in open_trades if t.ticker == ticker.upper()]
    
    if not open_trades:
        print("   Нет открытых сделок")
        return []
    
    print(f"   Найдено сделок: {len(open_trades)}")
    print()
    
    for trade in open_trades:
        print(f"📊 Сделка {trade.trade_id[:8]}...")
        print(f"   Тикер: {trade.ticker}")
        print(f"   Направление: {trade.direction}")
        print(f"   Вход: {format_currency(trade.entry_price_tick)}")
        print(f"   SL: {format_currency(trade.sl_price)}")
        print(f"   TP: {format_currency(trade.tp_price)}")
        print(f"   Лотов: {trade.entry_quantity_lots}")
        print(f"   Риск: {format_currency(trade.planned_risk_rub)} ({trade.risk_pct:.2f}%)")
        print(f"   Confidence: {trade.confidence}%")
        print(f"   Открыта: {trade.entry_time[:16]}")
        print(f"   Источник: {trade.source}")
        
        # Текущая цена и P&L
        try:
            from src.api.tbank import get_last_price
            current_price = get_last_price(trade.ticker)
            if current_price:
                if trade.direction == "BUY":
                    pnl = (current_price - trade.entry_price_tick) * trade.entry_quantity_shares
                    pnl_pct = (current_price - trade.entry_price_tick) / trade.entry_price_tick * 100
                else:
                    pnl = (trade.entry_price_tick - current_price) * trade.entry_quantity_shares
                    pnl_pct = (trade.entry_price_tick - current_price) / trade.entry_price_tick * 100
                
                print(f"   Текущая цена: {format_currency(current_price)}")
                print(f"   Текущий P&L: {format_currency(pnl)} ({pnl_pct:+.2f}%)")
        except Exception as e:
            print(f"   Не удалось получить текущую цену: {e}")
        
        print()


def cancel_trade(trade_id: str) -> bool:
    """Отменить сделку (все ордера)."""
    print(f"🚫 Отмена сделки {trade_id[:8]}...")
    
    # Получаем сделку
    trade = journal.get_trade(trade_id)
    if not trade:
        print(f"❌ Сделка {trade_id[:8]} не найдена")
        return False
    
    if trade.status != "OPEN":
        print(f"❌ Сделка {trade_id[:8]} уже закрыта (status: {trade.status})")
        return False
    
    # Получаем активные ордера
    try:
        orders = get_orders()
        trade_orders = []
        
        for order in orders:
            # Проверяем, принадлежит ли ордер нашей сделке
            if (order.get("figi") == trade.figi or 
                order.get("ticker") == trade.ticker):
                trade_orders.append(order)
        
        print(f"   Найдено ордеров для отмены: {len(trade_orders)}")
        
        # Отменяем все ордера
        cancelled_count = 0
        for order in trade_orders:
            order_id = order.get("orderId")
            if order_id:
                print(f"   Отмена ордера {order_id[:12]}...")
                result = cancel_order(order_id)
                if "error" not in result:
                    cancelled_count += 1
                    print(f"   ✅ Ордер отменен")
                else:
                    print(f"   ❌ Ошибка отмены: {result['error']}")
        
        # Обновляем статус сделки
        if cancelled_count > 0:
            journal.cancel_trade(trade_id)
            print(f"   ✅ Сделка отменена, {cancelled_count} ордеров отменено")
            return True
        else:
            print(f"   ❌ Не удалось отменить ни одного ордера")
            return False
            
    except Exception as e:
        print(f"❌ Ошибка при отмене сделки: {e}")
        return False


def close_trade_market(trade_id: str) -> bool:
    """Закрыть сделку по рыночной цене."""
    print(f"💥 Закрытие сделки {trade_id[:8]} по рыночной цене...")
    
    # Получаем сделку
    trade = journal.get_trade(trade_id)
    if not trade:
        print(f"❌ Сделка {trade_id[:8]} не найдена")
        return False
    
    if trade.status != "OPEN":
        print(f"❌ Сделка {trade_id[:8]} уже закрыта (status: {trade.status})")
        return False
    
    # Получаем текущую цену
    try:
        from src.api.tbank import get_last_price
        current_price = get_last_price(trade.ticker)
        if not current_price:
            print(f"❌ Не удалось получить текущую цену для {trade.ticker}")
            return False
        
        print(f"   Текущая цена: {format_currency(current_price)}")
        
        # Рассчитываем количество для продажи/покупки
        if trade.direction == "BUY":
            quantity = trade.entry_quantity_shares
            exit_reason = "MARKET_SELL"
        else:
            quantity = trade.entry_quantity_shares
            exit_reason = "MARKET_BUY"
        
        # Создаем рыночный ордер
        from src.api.tbank import place_limit_order
        market_order = place_limit_order(
            ticker=trade.ticker,
            direction=exit_reason,
            quantity_lots=trade.entry_quantity_lots,
            price_rub=current_price
        )
        
        if "error" in market_order:
            print(f"❌ Ошибка создания рыночного ордера: {market_order['error']}")
            return False
        
        print(f"   ✅ Рыночный ордер создан: {market_order.get('orderId', 'N/A')[:12]}...")
        
        # Закрываем сделку в журнале
        closed_trade = journal.close_trade(
            trade_id=trade_id,
            exit_price=current_price,
            exit_price_tick=current_price,
            exit_commission=0.0,  # Рыночный ордер - комиссия будет отдельной
            exit_reason=exit_reason.replace("MARKET_", ""),
            exit_order_id=market_order.get("orderId", "")
        )
        
        if closed_trade:
            print(f"   ✅ Сделка закрыта")
            print(f"   Выходная цена: {format_currency(current_price)}")
            
            # Рассчитываем P&L
            if trade.direction == "BUY":
                gross = (current_price - trade.entry_price_tick) * trade.entry_quantity_shares
            else:
                gross = (trade.entry_price_tick - current_price) * trade.entry_quantity_shares
            
            net_pnl = gross - trade.entry_commission  # Упрощенно без комиссии выхода
            print(f"   P&L: {format_currency(net_pnl)}")
            
            return True
        else:
            print(f"❌ Не удалось закрыть сделку в журнале")
            return False
            
    except Exception as e:
        print(f"❌ Ошибка при закрытии сделки: {e}")
        return False


def modify_sl(trade_id: str, new_sl: float) -> bool:
    """Изменить стоп-лосс."""
    print(f"🛑 Модификация SL для сделки {trade_id[:8]}...")
    print(f"   Новый SL: {format_currency(new_sl)}")
    
    # Получаем сделку
    trade = journal.get_trade(trade_id)
    if not trade:
        print(f"❌ Сделка {trade_id[:8]} не найдена")
        return False
    
    if trade.status != "OPEN":
        print(f"❌ Сделка {trade_id[:8]} уже закрыта (status: {trade.status})")
        return False
    
    # Отменяем старый SL
    if trade.get("sl_order_id"):
        print(f"   Отмена старого SL ордера {trade['sl_order_id'][:12]}...")
        result = cancel_order(trade["sl_order_id"])
        if "error" in result:
            print(f"   ❌ Ошибка отмены старого SL: {result['error']}")
            return False
    
    # Создаем новый SL
    try:
        from src.api.tbank import place_stop_order, round_to_tick
        
        new_sl_tick = round_to_tick(new_sl)
        sl_direction = "SELL" if trade.direction == "BUY" else "BUY"
        
        new_sl_order = place_stop_order(
            ticker=trade.ticker,
            direction=sl_direction,
            quantity_lots=trade.entry_quantity_lots,
            stop_price_rub=new_sl_tick,
            limit_price_rub=new_sl_tick
        )
        
        if "error" in new_sl_order:
            print(f"❌ Ошибка создания нового SL: {new_sl_order['error']}")
            return False
        
        print(f"   ✅ Новый SL ордер создан: {new_sl_order.get('stopOrderId', 'N/A')[:12]}...")
        
        # Обновляем сделку
        trade["sl_price"] = new_sl
        trade["sl_order_id"] = new_sl_order.get("stopOrderId", "")
        journal._save()
        
        print(f"   ✅ SL изменен")
        return True
        
    except Exception as e:
        print(f"❌ Ошибка при модификации SL: {e}")
        return False


def modify_tp(trade_id: str, new_tp: float) -> bool:
    """Изменить тейк-профит."""
    print(f"🎯 Модификация TP для сделки {trade_id[:8]}...")
    print(f"   Новый TP: {format_currency(new_tp)}")
    
    # Получаем сделку
    trade = journal.get_trade(trade_id)
    if not trade:
        print(f"❌ Сделка {trade_id[:8]} не найдена")
        return False
    
    if trade.status != "OPEN":
        print(f"❌ Сделка {trade_id[:8]} уже закрыта (status: {trade.status})")
        return False
    
    # Отменяем старый TP
    if trade.get("tp_order_id"):
        print(f"   Отмена старого TP ордера {trade['tp_order_id'][:12]}...")
        result = cancel_order(trade["tp_order_id"])
        if "error" in result:
            print(f"   ❌ Ошибка отмены старого TP: {result['error']}")
            return False
    
    # Создаем новый TP
    try:
        from src.api.tbank import place_stop_order, round_to_tick
        
        new_tp_tick = round_to_tick(new_tp)
        tp_direction = "SELL" if trade.direction == "BUY" else "BUY"
        
        new_tp_order = place_stop_order(
            ticker=trade.ticker,
            direction=tp_direction,
            quantity_lots=trade.entry_quantity_lots,
            stop_price_rub=new_tp_tick,
            stop_order_type="STOP_ORDER_TYPE_TAKE_PROFIT"
        )
        
        if "error" in new_tp_order:
            print(f"❌ Ошибка создания нового TP: {new_tp_order['error']}")
            return False
        
        print(f"   ✅ Новый TP ордер создан: {new_tp_order.get('stopOrderId', 'N/A')[:12]}...")
        
        # Обновляем сделку
        trade["tp_price"] = new_tp
        trade["tp_order_id"] = new_tp_order.get("stopOrderId", "")
        journal._save()
        
        print(f"   ✅ TP изменен")
        return True
        
    except Exception as e:
        print(f"❌ Ошибка при модификации TP: {e}")
        return False


def monitor_trade(trade_id: str, interval: int = 900) -> None:
    """Мониторинг сделки."""
    print(f"👁️ Запуск мониторинга для сделки {trade_id[:8]}...")
    print(f"   Интервал: {interval}с ({interval//60} мин)")
    
    # Импортируем монитор
    from src.monitor_trade import monitor_trade as monitor_func
    
    # Запускаем мониторинг
    try:
        # Получаем сделку для получения тикера
        trade = journal.get_trade(trade_id)
        if not trade:
            print(f"❌ Сделка {trade_id[:8]} не найдена")
            return
        
        monitor_func(trade.ticker, trade_id, interval_sec=interval)
        
    except KeyboardInterrupt:
        print("⏹ Мониторинг остановлен пользователем")
    except Exception as e:
        print(f"❌ Ошибка при мониторинге: {e}")


def main():
    parser = argparse.ArgumentParser(
        description="Управление существующими сделками"
    )
    parser.add_argument("--env", choices=["sandbox", "real"], default="sandbox", 
                       help="Окружение T-Bank API")
    
    # Действия
    action_group = parser.add_mutually_exclusive_group(required=True)
    action_group.add_argument("--list", action="store_true", help="Показать открытые сделки")
    action_group.add_argument("--cancel", action="store_true", help="Отменить сделку")
    action_group.add_argument("--close", action="store_true", help="Закрыть сделку по рыночной цене")
    action_group.add_argument("--modify-sl", action="store_true", help="Изменить SL")
    action_group.add_argument("--modify-tp", action="store_true", help="Изменить TP")
    action_group.add_argument("--monitor", action="store_true", help="Мониторить сделку")
    
    # Параметры
    parser.add_argument("--ticker", help="Фильтр по тикеру (для --list)")
    parser.add_argument("--trade-id", help="ID сделки")
    parser.add_argument("--new-sl", type=float, help="Новый SL (для --modify-sl)")
    parser.add_argument("--new-tp", type=float, help="Новый TP (для --modify-tp)")
    parser.add_argument("--interval", type=int, default=900, help="Интервал мониторинга в секундах")
    
    args = parser.parse_args()
    
    # Установка окружения
    print(f"🔄 Установка окружения: {args.env}...")
    set_tbank_env(args.env)
    
    if args.list:
        list_open_trades(args.ticker)
    
    elif args.cancel:
        if not args.trade_id:
            print("❌ Укажите --trade-id для отмены сделки")
            sys.exit(1)
        
        success = cancel_trade(args.trade_id)
        if success:
            print("✅ Сделка успешно отменена")
        else:
            print("❌ Не удалось отменить сделку")
            sys.exit(1)
    
    elif args.close:
        if not args.trade_id:
            print("❌ Укажите --trade-id для закрытия сделки")
            sys.exit(1)
        
        success = close_trade_market(args.trade_id)
        if success:
            print("✅ Сделка успешно закрыта")
        else:
            print("❌ Не удалось закрыть сделку")
            sys.exit(1)
    
    elif args.modify_sl:
        if not args.trade_id or not args.new_sl:
            print("❌ Укажите --trade-id и --new-sl для изменения SL")
            sys.exit(1)
        
        success = modify_sl(args.trade_id, args.new_sl)
        if success:
            print("✅ SL успешно изменен")
        else:
            print("❌ Не удалось изменить SL")
            sys.exit(1)
    
    elif args.modify_tp:
        if not args.trade_id or not args.new_tp:
            print("❌ Укажите --trade-id и --new-tp для изменения TP")
            sys.exit(1)
        
        success = modify_tp(args.trade_id, args.new_tp)
        if success:
            print("✅ TP успешно изменен")
        else:
            print("❌ Не удалось изменить TP")
            sys.exit(1)
    
    elif args.monitor:
        if not args.trade_id:
            print("❌ Укажите --trade-id для мониторинга")
            sys.exit(1)
        
        monitor_trade(args.trade_id, args.interval)


if __name__ == "__main__":
    main()