import MetaTrader5 as mt5
import time

tracked_positions = {}


def get_profit(position):
    return position.profit


def profit_to_price(symbol, profit, volume):
    info = mt5.symbol_info(symbol)

    tick_value = info.trade_tick_value
    tick_size = info.trade_tick_size

    return (profit / (tick_value * volume)) * tick_size


def calculate_sl(position, profit):
    if profit < 5:
        return None

    symbol = position.symbol
    volume = position.volume

    base_lock = 4
    steps = int((profit - 5) // 2)
    locked_profit = base_lock + steps

    price_distance = profit_to_price(symbol, locked_profit, volume)

    if position.type == mt5.ORDER_TYPE_BUY:
        return position.price_open + price_distance
    else:
        return position.price_open - price_distance


def is_valid_sl(position, sl):
    symbol = position.symbol
    info = mt5.symbol_info(symbol)
    tick = mt5.symbol_info_tick(symbol)

    stops_level = info.trade_stops_level * info.point

    if position.type == mt5.ORDER_TYPE_BUY:
        return sl < tick.bid - stops_level
    else:
        return sl > tick.ask + stops_level


def should_update_sl(position, new_sl):
    """
    Only allow SL to move in profitable direction
    """
    current_sl = position.sl

    if position.type == mt5.ORDER_TYPE_BUY:
        return current_sl == 0.0 or new_sl > current_sl
    else:
        return current_sl == 0.0 or new_sl < current_sl


def manage_trades():
    while True:
        positions = mt5.positions_get()

        if not positions:
            time.sleep(2)
            continue

        for pos in positions:
            profit = get_profit(pos)

            new_sl = calculate_sl(pos, profit)
            if new_sl is None:
                continue

            # must be valid SL level
            if not is_valid_sl(pos, new_sl):
                continue

            # only improve SL, never worsen it
            if not should_update_sl(pos, new_sl):
                continue

            request = {
                "action": mt5.TRADE_ACTION_SLTP,
                "position": pos.ticket,
                "sl": round(new_sl, 2),
                "tp": pos.tp,
            }

            result = mt5.order_send(request)

            print(f"🔄 SL updated {pos.ticket}: {result}")

            if result.retcode == mt5.TRADE_RETCODE_DONE:
                tracked_positions[pos.ticket] = new_sl

        time.sleep(5)