"""
تنظیمات ذخیره‌شدهٔ ربات (روی دیسک) با ادغام روی مقادیر .env.
هر چت مجاز می‌تواند مقادیر خود را داشته باشد.
"""

from __future__ import annotations

import json
import os
import threading
from dataclasses import dataclass, fields
from pathlib import Path

_lock = threading.Lock()
_FILE = Path(__file__).resolve().parent / "bot_settings.json"


@dataclass
class UserBotConfig:
    default_symbol: str
    default_max_lot_per_order: float
    magic: int
    deviation_points: int
    comment: str
    risk_max_total_lots: float
    risk_max_split_orders: int
    risk_margin_buffer_percent: float
    risk_min_free_margin_percent_of_equity: float

    def risk_tuple(self) -> tuple[float, int, float, float]:
        return (
            self.risk_max_total_lots,
            self.risk_max_split_orders,
            self.risk_margin_buffer_percent,
            self.risk_min_free_margin_percent_of_equity,
        )


def _env_defaults() -> dict:
    return {
        "default_symbol": os.getenv("DEFAULT_SYMBOL", "XAUUSD.p").strip(),
        "default_max_lot_per_order": float(os.getenv("DEFAULT_MAX_LOT_PER_ORDER", "5")),
        "magic": int(os.getenv("MAGIC", "20260512")),
        "deviation_points": int(os.getenv("DEVIATION_POINTS", "30")),
        "comment": os.getenv("COMMENT", "LotSplitTG").strip(),
        "risk_max_total_lots": float(
            os.getenv("RISK_MAX_TOTAL_LOTS", "500").strip() or "500"
        ),
        "risk_max_split_orders": int(os.getenv("RISK_MAX_SPLIT_ORDERS", "2000")),
        "risk_margin_buffer_percent": float(
            os.getenv("RISK_MARGIN_BUFFER_PERCENT", "10")
        ),
        "risk_min_free_margin_percent_of_equity": float(
            os.getenv("RISK_MIN_FREE_MARGIN_PERCENT_OF_EQUITY", "5")
        ),
    }


def _read_raw() -> dict:
    if not _FILE.is_file():
        return {"chats": {}}
    try:
        with open(_FILE, encoding="utf-8") as f:
            data = json.load(f)
        if not isinstance(data, dict):
            return {"chats": {}}
        data.setdefault("chats", {})
        return data
    except (OSError, json.JSONDecodeError):
        return {"chats": {}}


def _write_raw(data: dict) -> None:
    _FILE.parent.mkdir(parents=True, exist_ok=True)
    tmp = _FILE.with_suffix(".tmp")
    with open(tmp, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    tmp.replace(_FILE)


def get_config(chat_id: int) -> UserBotConfig:
    with _lock:
        base = _env_defaults()
        raw = _read_raw()
        ov = raw.get("chats", {}).get(str(chat_id), {})
        if isinstance(ov, dict):
            for k, v in ov.items():
                if k in base and v is not None:
                    base[k] = v
        # نوع‌دهی
        base["default_max_lot_per_order"] = float(base["default_max_lot_per_order"])
        base["magic"] = int(base["magic"])
        base["deviation_points"] = int(base["deviation_points"])
        base["risk_max_total_lots"] = max(0.0, float(base["risk_max_total_lots"]))
        base["risk_max_split_orders"] = max(1, int(base["risk_max_split_orders"]))
        base["risk_margin_buffer_percent"] = float(base["risk_margin_buffer_percent"])
        base["risk_min_free_margin_percent_of_equity"] = float(
            base["risk_min_free_margin_percent_of_equity"]
        )
        ds = str(base.get("default_symbol", "")).strip()
        if not ds:
            ds = str(_env_defaults()["default_symbol"]).strip() or "XAUUSD.p"
        return UserBotConfig(
            default_symbol=ds,
            default_max_lot_per_order=float(base["default_max_lot_per_order"]),
            magic=int(base["magic"]),
            deviation_points=int(base["deviation_points"]),
            comment=str(base["comment"])[:64],
            risk_max_total_lots=float(base["risk_max_total_lots"]),
            risk_max_split_orders=int(base["risk_max_split_orders"]),
            risk_margin_buffer_percent=float(base["risk_margin_buffer_percent"]),
            risk_min_free_margin_percent_of_equity=float(
                base["risk_min_free_margin_percent_of_equity"]
            ),
        )


def update_config(chat_id: int, **field_updates: object) -> UserBotConfig:
    allowed = {f.name for f in fields(UserBotConfig)}
    with _lock:
        data = _read_raw()
        chats = data.setdefault("chats", {})
        cur: dict = dict(chats.get(str(chat_id), {}))
        for k, v in field_updates.items():
            if k in allowed and v is not None:
                cur[k] = v
        chats[str(chat_id)] = cur
        _write_raw(data)
    return get_config(chat_id)


def reset_config(chat_id: int) -> None:
    with _lock:
        data = _read_raw()
        chats = data.setdefault("chats", {})
        chats.pop(str(chat_id), None)
        _write_raw(data)
