# app/src/telegram/handlers/system.py

from __future__ import annotations

import os

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, InaccessibleMessage, InlineKeyboardMarkup, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder

from src.core.config import ENV_FILE, load_settings
from src.core.constants import APP_NAME, APP_VERSION
from src.core.numbers import safe_float
from src.core.system_status import build_system_text, get_system_snapshot, has_system_alerts
from src.core.types import JsonDict, NumericLike
from src.telegram.live.active_screen import ActiveScreenManager
from src.telegram.live.runner import LiveScreenRunner, ScreenRegistry, StaticScreen
from src.trading.auto.service import AutoTradeService
from src.trading.journal.service import JournalService


router = Router(name="system")


def _require_message(callback: CallbackQuery) -> Message | None:
    message = callback.message

    if message is None or isinstance(message, InaccessibleMessage):
        return None

    return message


def _system_keyboard() -> InlineKeyboardMarkup:
    builder = InlineKeyboardBuilder()
    builder.button(text="🛠️ Настройки", callback_data="system:management")
    builder.button(text="📒 Журнал", callback_data="system:journal")
    builder.button(text="ℹ️ Информация", callback_data="system:about")
    builder.adjust(2, 1)
    return builder.as_markup()


def _system_alert_keyboard() -> InlineKeyboardMarkup:
    builder = InlineKeyboardBuilder()
    builder.button(text="🔁 Обновить", callback_data="system:retry")
    builder.button(text="🛠️ Настройки", callback_data="system:management")
    builder.button(text="📒 Журнал", callback_data="system:journal")
    builder.button(text="ℹ️ Информация", callback_data="system:about")
    builder.adjust(1, 2, 1)
    return builder.as_markup()


def _register_system_screen(message: Message, screen: str = "system") -> None:
    bot = message.bot

    if bot is None:
        return

    LiveScreenRunner.unregister_message(
        chat_id=message.chat.id,
        message_id=message.message_id,
    )
    ScreenRegistry.unregister_message(
        chat_id=message.chat.id,
        message_id=message.message_id,
    )

    ScreenRegistry.register_screen(
        StaticScreen(
            screen=screen,
            bot=bot,
            chat_id=message.chat.id,
            message_id=message.message_id,
        )
    )

    ActiveScreenManager.register(
        screen=screen,
        message=message,
    )


async def _prepare_system_from_message(
    message: Message,
    screen: str = "system",
) -> bool:
    bot = message.bot

    if bot is None:
        return False

    await ActiveScreenManager.prepare_new_screen(
        screen=screen,
        bot=bot,
        chat_id=message.chat.id,
    )

    return True


async def _prepare_system_from_callback(
    callback: CallbackQuery,
    screen: str = "system",
) -> bool:
    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return False

    bot = message.bot

    if bot is None:
        await callback.answer("Bot недоступен", show_alert=True)
        return False

    await ActiveScreenManager.prepare_new_screen(
        screen=screen,
        bot=bot,
        chat_id=message.chat.id,
        keep_message_id=message.message_id,
    )

    return True


async def _render_system_screen(
    target_message: Message,
    *,
    edit_mode: bool,
    user_id: int | None,
    chat_id: int | None,
    action: str,
) -> None:
    journal = JournalService()

    snapshot = get_system_snapshot()
    is_alert = has_system_alerts(snapshot)

    if is_alert:
        journal.log_ui_warning(
            event_type="system_open_alert",
            message="Система загружена с предупреждениями.",
            screen="system",
            action=action,
            user_id=user_id,
            chat_id=chat_id,
            payload={
                "has_alerts": True,
                "components": [
                    {
                        "name": component.name,
                        "state": component.state,
                        "details": component.details,
                    }
                    for component in snapshot.components
                    if component.state != "🟢"
                ],
            },
        )
    else:
        journal.log_ui_info(
            event_type="system_open_success",
            message="Экран системы загружен.",
            screen="system",
            action=action,
            user_id=user_id,
            chat_id=chat_id,
            payload={"has_alerts": False},
        )

    text = build_system_text(include_updated_at=is_alert)
    reply_markup = _system_alert_keyboard() if is_alert else _system_keyboard()

    if edit_mode:
        await target_message.edit_text(text, reply_markup=reply_markup)
        _register_system_screen(target_message, screen="system")
        return

    sent_message = await target_message.answer(text, reply_markup=reply_markup)
    _register_system_screen(sent_message, screen="system")


@router.message(F.text.in_({"🖥️ Система"}))
async def open_system(message: Message, state: FSMContext) -> None:
    await state.clear()

    if not await _prepare_system_from_message(message, screen="system"):
        return

    user_id = message.from_user.id if message.from_user else None
    chat_id = message.chat.id if message.chat else None

    await _render_system_screen(
        message,
        edit_mode=False,
        user_id=user_id,
        chat_id=chat_id,
        action="open",
    )


@router.callback_query(F.data == "system:retry")
async def retry_system(callback: CallbackQuery, state: FSMContext) -> None:
    await state.clear()

    if not await _prepare_system_from_callback(callback, screen="system"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    user_id = callback.from_user.id if callback.from_user else None
    chat_id = message.chat.id

    await _render_system_screen(
        message,
        edit_mode=True,
        user_id=user_id,
        chat_id=chat_id,
        action="retry",
    )

    await callback.answer()


@router.callback_query(F.data == "system:management")
async def open_system_management(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="system"):
        return

    text = (
        "<b>🛠️ Настройки</b>\n\n"
        "<b>СИСТЕМА</b>\n\n"
        "Выберите раздел:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="🤖 Автоторговля", callback_data="settings:auto")
    builder.button(text="🌍 Общие", callback_data="settings:general")
    builder.button(text="📒 Журнал", callback_data="settings:journal")
    builder.button(text="⬅️ Назад", callback_data="system:back")
    builder.adjust(1, 2, 1)

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="system")
    await callback.answer()


@router.callback_query(F.data == "settings:auto")
async def open_auto_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    state = AutoTradeService().get_state()

    strategy_map = {
        "TREND": "TREND FOLLOWING",
        "GRID": "GRID TRADING",
        "SCALP": "SCALPING",
    }

    strategy_ready = state.strategy is not None
    symbol_ready = bool(state.symbol)
    risk_ready = state.risk_percent is not None
    leverage_ready = state.leverage is not None

    is_trend_strategy = (state.strategy or "").upper() == "TREND"
    sl_ready = state.stop_loss_percent is not None and state.stop_loss_percent > 0

    is_configured = (
        strategy_ready
        and symbol_ready
        and risk_ready
        and leverage_ready
        and (not is_trend_strategy or sl_ready)
    )

    strategy = strategy_map.get(state.strategy or "", "—")
    symbol = _human_symbol(state.symbol)
    risk = _format_number(state.risk_percent, suffix="%", default="—")

    leverage_value = safe_float(state.leverage)
    leverage = f"x{leverage_value:g}" if leverage_value is not None else "—"

    max_reserved = _format_percent_setting(state.max_reserved_balance_percent)
    sl = _format_percent_setting(state.stop_loss_percent)
    tp = _format_percent_setting(state.take_profit_percent)

    ml_value = safe_float(state.max_loss_usd)
    ml = f"{ml_value:g} USD" if ml_value is not None else "off"

    strategy_icon = "✅" if strategy_ready else "⚠️"
    symbol_icon = "✅" if symbol_ready else "⚠️"
    risk_icon = "✅" if risk_ready else "⚠️"
    leverage_icon = "✅" if leverage_ready else "⚠️"
    sl_icon = "⛔️" if is_trend_strategy and not sl_ready else ("✅" if state.stop_loss_percent is not None else "⚠️")
    tp_icon = "✅" if state.take_profit_percent is not None else "⚠️"
    ml_icon = "✅" if state.max_loss_usd is not None else "⚠️"

    settings_status_icon = "✅" if is_configured else "⛔️"
    config_status = "" if is_configured else "\n\nНастрой все параметры"

    text = (
        "<b>🤖 Автоторговля</b>\n\n"
        f"<b>СИСТЕМА</b> · Настройки {settings_status_icon}\n\n"
        f"{strategy_icon} Стратегия: <b>{strategy}</b>\n"
        f"{symbol_icon} Актив: <b>{symbol}</b>\n"
        f"{risk_icon} Риск на сделку: <b>{risk}</b>\n"
        f"{leverage_icon} Плечо: <b>{leverage}</b>\n\n"
        f"✅ Лимит на сделку: <b>{max_reserved}</b>\n\n"
        "<b>Защита позиции:</b>\n"
        f"{sl_icon} Stop Loss · {sl}\n"
        f"{tp_icon} Take Profit · {tp}\n"
        f"{ml_icon} Max Loss · {ml}"
        f"{config_status}"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="🧠 Стратегия", callback_data="settings:auto_strategy")
    builder.button(text="💱 Актив", callback_data="settings:auto_symbol")
    builder.button(text="⚙️ Плечо", callback_data="settings:auto_leverage")
    builder.button(text="🏦 Лимит", callback_data="settings:auto_max_reserved")
    builder.button(text="🛡️ Риск", callback_data="settings:auto_risk")
    builder.button(text="🧯 Защита", callback_data="auto:risk")
    builder.button(text="🤖 Автоторговля", callback_data="auto:home")
    builder.button(text="⬅️ Назад", callback_data="system:management")
    builder.adjust(2, 2, 2, 2)

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


@router.callback_query(F.data == "settings:auto_strategy")
async def open_auto_strategy_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>🧠 Стратегия</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
        "Выберите стратегию:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="📈 Trend", callback_data="settings:auto_strategy:trend")
    builder.button(text="🧩 Grid", callback_data="settings:auto_strategy:grid")
    builder.button(text="⚡ Scalp", callback_data="settings:auto_strategy:scalp")
    builder.button(text="⬅️ Назад", callback_data="settings:auto")
    builder.adjust(3, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


def _log_auto_setting_updated(
    *,
    event_type: str = "auto_settings_updated",
    message: str,
    action: str,
    payload: JsonDict,
) -> None:
    try:
        JournalService().log_ui_info(
            event_type=event_type,
            message=message,
            screen="settings_auto",
            action=action,
            payload=payload,
        )
    except Exception:
        pass


def _human_symbol(symbol: str | None) -> str:
    if not symbol:
        return "—"

    base = symbol.split("_", 1)[0].upper()

    if "/" in base:
        return base.split("/", 1)[0]

    for suffix in ("USDT", "USD", "EUR", "BTC"):
        if base.endswith(suffix) and len(base) > len(suffix):
            return base[: -len(suffix)]

    return base


def _format_number(
    value: NumericLike | None,
    *,
    suffix: str = "",
    default: str = "—",
) -> str:
    number = safe_float(value)

    if number is None:
        return default

    return f"{number:g}{suffix}"


def _format_percent_setting(value: NumericLike | None) -> str:
    return _format_number(value, suffix="%", default="off")


def _parse_callback_float(value: object) -> float | None:
    return safe_float(value)


@router.callback_query(F.data.startswith("settings:auto_strategy:"))
async def set_auto_strategy(callback: CallbackQuery) -> None:
    data = callback.data or ""
    parts = data.split(":", 2)

    if len(parts) < 3:
        await callback.answer("Некорректное значение стратегии", show_alert=True)
        return

    strategy = parts[2].upper()

    service = AutoTradeService()
    state = service.get_state()
    previous_strategy = state.strategy

    service.set_strategy(strategy)

    if previous_strategy != strategy:
        _log_auto_setting_updated(
            message=f"Стратегия изменена: {strategy}.",
            action="set_strategy",
            payload={
                "previous_strategy": previous_strategy,
                "strategy": strategy,
            },
        )

    await open_auto_settings(callback)
    await callback.answer("Стратегия обновлена")


@router.callback_query(F.data == "settings:auto_symbol")
async def open_auto_symbol_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>💱 Актив</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
        "Выберите актив:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="BTC", callback_data="settings:auto_symbol:BTC/USD_LEVERAGE")
    builder.button(text="ETH", callback_data="settings:auto_symbol:ETH/USD_LEVERAGE")
    builder.button(text="LTC", callback_data="settings:auto_symbol:LTC/USD_LEVERAGE")
    builder.button(text="XRP", callback_data="settings:auto_symbol:XRP/USD_LEVERAGE")
    builder.button(text="⬅️ Назад", callback_data="settings:auto")
    builder.adjust(2, 2, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


@router.callback_query(F.data.startswith("settings:auto_symbol:"))
async def set_auto_symbol(callback: CallbackQuery) -> None:
    data = callback.data or ""
    parts = data.split(":", 2)

    if len(parts) < 3:
        await callback.answer("Некорректное значение актива", show_alert=True)
        return

    symbol = parts[2]

    service = AutoTradeService()
    state = service.get_state()
    previous_symbol = state.symbol

    service.set_symbol(symbol)

    if previous_symbol != symbol:
        _log_auto_setting_updated(
            message=f"Актив изменён: {_human_symbol(symbol)}.",
            action="set_symbol",
            payload={
                "previous_symbol": previous_symbol,
                "symbol": symbol,
            },
        )

    await open_auto_settings(callback)
    await callback.answer("Актив обновлён")


@router.callback_query(F.data == "settings:auto_risk")
async def open_auto_risk_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>🛡️ Риск на сделку</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
        "Выберите риск на сделку:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="0.5%", callback_data="settings:auto_risk:0.5")
    builder.button(text="1.0%", callback_data="settings:auto_risk:1.0")
    builder.button(text="2.0%", callback_data="settings:auto_risk:2.0")
    builder.button(text="⬅️ Назад", callback_data="settings:auto")
    builder.adjust(3, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


@router.callback_query(F.data.startswith("settings:auto_risk:"))
async def set_auto_risk(callback: CallbackQuery) -> None:
    data = callback.data or ""
    parts = data.split(":", 2)

    if len(parts) < 3:
        await callback.answer("Некорректное значение риска", show_alert=True)
        return

    risk = _parse_callback_float(parts[2])

    if risk is None:
        await callback.answer("Некорректное значение риска", show_alert=True)
        return

    service = AutoTradeService()
    state = service.get_state()
    previous_risk = state.risk_percent

    service.set_risk_percent(risk)

    if previous_risk != risk:
        _log_auto_setting_updated(
            message=f"Риск на сделку изменён: {risk:g}%.",
            action="set_risk_percent",
            payload={
                "previous_risk_percent": previous_risk,
                "risk_percent": risk,
            },
        )

    await open_auto_settings(callback)
    await callback.answer("Риск обновлён")


@router.callback_query(F.data == "settings:auto_leverage")
async def open_auto_leverage_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>⚙️ Плечо</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
        "Выберите плечо:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="x1", callback_data="settings:auto_leverage:1")
    builder.button(text="x2", callback_data="settings:auto_leverage:2")
    builder.button(text="x3", callback_data="settings:auto_leverage:3")
    builder.button(text="x5", callback_data="settings:auto_leverage:5")
    builder.button(text="x10", callback_data="settings:auto_leverage:10")
    builder.button(text="x20", callback_data="settings:auto_leverage:20")
    builder.button(text="⬅️ Назад", callback_data="settings:auto")
    builder.adjust(3, 3, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


@router.callback_query(F.data.startswith("settings:auto_leverage:"))
async def set_auto_leverage(callback: CallbackQuery) -> None:
    data = callback.data or ""
    parts = data.split(":", 2)

    if len(parts) < 3:
        await callback.answer("Некорректное значение плеча", show_alert=True)
        return

    leverage = _parse_callback_float(parts[2])

    if leverage is None:
        await callback.answer("Некорректное значение плеча", show_alert=True)
        return

    service = AutoTradeService()
    state = service.get_state()
    previous_leverage = state.leverage

    service.set_leverage(leverage)

    if previous_leverage != leverage:
        _log_auto_setting_updated(
            message=f"Плечо изменено: x{leverage:g}.",
            action="set_leverage",
            payload={
                "previous_leverage": previous_leverage,
                "leverage": leverage,
            },
        )

    await open_auto_settings(callback)
    await callback.answer("Плечо обновлено")


@router.callback_query(F.data == "settings:auto_max_reserved")
async def open_auto_max_reserved_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_auto"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>🏦 Лимит на сделку</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
        "Максимальная доля баланса, которую можно зарезервировать под позицию:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="25%", callback_data="settings:auto_max_reserved:25")
    builder.button(text="50%", callback_data="settings:auto_max_reserved:50")
    builder.button(text="75%", callback_data="settings:auto_max_reserved:75")
    builder.button(text="100%", callback_data="settings:auto_max_reserved:100")
    builder.button(text="off", callback_data="settings:auto_max_reserved:off")
    builder.button(text="⬅️ Назад", callback_data="settings:auto")
    builder.adjust(2, 2, 1, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_auto")
    await callback.answer()


@router.callback_query(F.data.startswith("settings:auto_max_reserved:"))
async def set_auto_max_reserved(callback: CallbackQuery) -> None:
    data = callback.data or ""
    parts = data.split(":", 2)

    if len(parts) < 3:
        await callback.answer("Некорректные данные кнопки", show_alert=True)
        return

    raw_value = parts[2]
    value = None if raw_value == "off" else _parse_callback_float(raw_value)

    if raw_value != "off" and value is None:
        await callback.answer("Некорректное значение лимита", show_alert=True)
        return

    service = AutoTradeService()
    state = service.get_state()
    previous_value = state.max_reserved_balance_percent

    service.set_max_reserved_balance_percent(value)

    if previous_value != value:
        value_text = "off" if value is None else f"{value:g}%"

        _log_auto_setting_updated(
            message=f"Лимит на сделку изменён: {value_text}.",
            action="set_max_reserved_balance_percent",
            payload={
                "previous_max_reserved_balance_percent": previous_value,
                "max_reserved_balance_percent": value,
            },
        )

    await open_auto_settings(callback)
    await callback.answer("Лимит обновлён")


@router.callback_query(F.data == "settings:general")
async def open_general_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_general"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>🌍 Общие</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки\n\n"
        "Режим аккаунта: —\n"
        "Часовой пояс: —\n"
        "Язык интерфейса: ru\n\n"
        "В разработке."
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="⬅️ Назад", callback_data="system:management")
    builder.adjust(1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_general")
    await callback.answer()


def _journal_debug_enabled() -> bool:
    return bool(load_settings().journal_debug_enabled)


def _set_env_value(key: str, value: str) -> None:
    lines: list[str] = []

    if ENV_FILE.exists():
        lines = ENV_FILE.read_text(encoding="utf-8").splitlines()

    updated = False
    result: list[str] = []

    for line in lines:
        if line.strip().startswith(f"{key}="):
            result.append(f"{key}={value}")
            updated = True
        else:
            result.append(line)

    if not updated:
        result.append(f"{key}={value}")

    ENV_FILE.write_text("\n".join(result) + "\n", encoding="utf-8")
    os.environ[key] = value


def _journal_debug_status_line() -> str:
    if _journal_debug_enabled():
        return "🐞 Debug лог: <b>ВКЛ</b>"

    return "🐞 Debug лог: <b>ВЫКЛ</b>"


@router.callback_query(F.data == "settings:journal")
async def open_journal_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_journal"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    service = JournalService()
    total = service.get_total_count()

    text = (
        "<b>📒 Журнал</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки\n\n"
        f"📄 Записей: {total}\n"
        f"{_journal_debug_status_line()}\n"
        "📦 Лимит: —\n"
        "⏳ Хранение: —\n"
        "🗄 Архив: —\n\n"
    )

    debug_button_text = (
        "🟢 Debug логирование"
        if _journal_debug_enabled()
        else "⚪️ Debug логирование"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text=debug_button_text, callback_data="settings:journal_debug_toggle")
    builder.button(text="🗑 Очистка", callback_data="journal:clear_confirm")
    builder.button(text="🗄 Архив", callback_data="settings:journal_archive")
    builder.button(text="📦 Лимит", callback_data="settings:journal_limit")
    builder.button(text="⏳ Хранение", callback_data="settings:journal_retention")
    builder.button(text="⬅️ Назад", callback_data="system:management")
    builder.button(text="📒 Журнал", callback_data="journal:1")
    builder.adjust(1, 2, 2, 2)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_journal")
    await callback.answer()


@router.callback_query(F.data == "settings:journal_debug_toggle")
async def toggle_journal_debug(callback: CallbackQuery) -> None:
    enabled = _journal_debug_enabled()
    new_value = "false" if enabled else "true"

    _set_env_value("JOURNAL_DEBUG_ENABLED", new_value)

    try:
        JournalService().log_ui_info(
            event_type="journal_debug_changed",
            message=(
                "Debug логирование журнала выключено."
                if enabled
                else "Debug логирование журнала включено."
            ),
            screen="settings_journal",
            action="toggle_debug",
            payload={
                "journal_debug_enabled": not enabled,
            },
        )
    except Exception:
        pass

    await open_journal_settings(callback)

    await callback.answer(
        "Debug логирование выключено" if enabled else "Debug логирование включено"
    )


@router.callback_query(F.data == "settings:journal_archive")
async def open_journal_archive_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_journal"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>🗄 Архив</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Журнал\n\n"
        "Автоматический архив журнала: —\n"
        "Формат архива: —\n"
        "Периодичность: —\n\n"
        "В разработке."
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="⬅️ Назад", callback_data="settings:journal")
    builder.button(text="📒 Журнал", callback_data="journal:1")
    builder.adjust(2)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_journal")
    await callback.answer()


@router.callback_query(F.data == "settings:journal_limit")
async def open_journal_limit_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_journal"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>📦 Лимит</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Журнал\n\n"
        "Текущий лимит: —\n\n"
        "Доступные варианты:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="1 000", callback_data="settings:journal_limit_stub")
    builder.button(text="5 000", callback_data="settings:journal_limit_stub")
    builder.button(text="10 000", callback_data="settings:journal_limit_stub")
    builder.button(text="∞", callback_data="settings:journal_limit_stub")
    builder.button(text="⬅️ Назад", callback_data="settings:journal")
    builder.adjust(2, 2, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_journal")
    await callback.answer()


@router.callback_query(F.data == "settings:journal_retention")
async def open_journal_retention_settings(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="settings_journal"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    text = (
        "<b>⏳ Хранение</b>\n\n"
        "<b>СИСТЕМА</b> · Настройки · Журнал\n\n"
        "Текущий срок хранения: —\n\n"
        "Доступные варианты:"
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="7 дней", callback_data="settings:journal_retention_stub")
    builder.button(text="30 дней", callback_data="settings:journal_retention_stub")
    builder.button(text="90 дней", callback_data="settings:journal_retention_stub")
    builder.button(text="∞", callback_data="settings:journal_retention_stub")
    builder.button(text="⬅️ Назад", callback_data="settings:journal")
    builder.adjust(2, 2, 1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="settings_journal")
    await callback.answer()


@router.callback_query(
    F.data.in_(
        {
            "settings:journal_limit_stub",
            "settings:journal_retention_stub",
        }
    )
)
async def journal_settings_stub(callback: CallbackQuery) -> None:
    await callback.answer("Настройка скоро появится", show_alert=True)


@router.callback_query(F.data == "system:back")
async def back_to_system(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="system"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    user_id = callback.from_user.id if callback.from_user else None
    chat_id = message.chat.id

    await _render_system_screen(
        message,
        edit_mode=True,
        user_id=user_id,
        chat_id=chat_id,
        action="back",
    )

    await callback.answer()


@router.callback_query(F.data == "system:about")
async def open_system_about(callback: CallbackQuery) -> None:
    if not await _prepare_system_from_callback(callback, screen="system_about"):
        return

    message = _require_message(callback)

    if message is None:
        await callback.answer("Сообщение недоступно", show_alert=True)
        return

    settings = load_settings()
    journal = JournalService()

    journal.log_ui_info(
        event_type="system_about_opened",
        message="Открыта информация о продукте.",
        screen="system",
        action="about",
        user_id=callback.from_user.id if callback.from_user else None,
        chat_id=message.chat.id,
    )

    text = (
        "<b>ℹ️ Информация</b>\n\n"
        "<b>СИСТЕМА</b>\n\n"
        f"<b>{APP_NAME}</b>\n"
        f"Версия: {APP_VERSION}\n"
        f"Режим: {'DEMO' if 'demo' in settings.exchange_base_url.lower() else 'LIVE'}\n"
        f"Часовой пояс: {settings.tz}\n\n"
        "Торговый Telegram-бот для контроля рынка, портфеля, журнала событий "
        "и автоторговли."
    )

    builder = InlineKeyboardBuilder()
    builder.button(text="⬅️ Назад", callback_data="system:back")
    builder.adjust(1)

    await message.edit_text(text, reply_markup=builder.as_markup())
    _register_system_screen(message, screen="system_about")
    await callback.answer()