from __future__ import annotations

from datetime import datetime, timezone
from typing import Any


_registry: dict[str, dict[str, Any]] = {}


def _position_key(account: str | None, ticker: str) -> str:
    acct = (account or "").strip() or "default"
    return f"{acct}|{ticker.strip()}"


def sync_positions(positions: list[dict[str, Any]], *, source: str) -> list[dict[str, Any]]:
    """Remplace les positions SL connues pour une source (ninja)."""
    now = datetime.now(timezone.utc).isoformat()
    incoming_keys: set[str] = set()
    normalized: list[dict[str, Any]] = []

    for raw in positions:
        if not isinstance(raw, dict):
            continue
        ticker = str(raw.get("ticker") or raw.get("instrument") or "").strip()
        if not ticker:
            continue
        account = str(raw.get("account") or "").strip() or None
        key = _position_key(account, ticker)
        incoming_keys.add(key)

        side = str(raw.get("side") or raw.get("action") or "buy").strip().lower()
        if side in ("long", "buy"):
            side = "buy"
        elif side in ("short", "sell"):
            side = "sell"

        entry = _to_float(raw.get("entry_price") or raw.get("price"))
        stop = _to_float(raw.get("stop_loss") or raw.get("stop"))
        qty = _to_float(raw.get("quantity") or raw.get("qty")) or 0.0
        modify_count = int(_to_float(raw.get("sl_modify_count")) or 0)

        row = {
            "id": key,
            "ticker": ticker,
            "account": account,
            "side": side,
            "quantity": round(qty, 6),
            "entry_price": entry,
            "stop_loss": stop,
            "sl_modify_count": max(0, modify_count),
            "source": source,
            "updated_at": now,
        }
        _registry[key] = row
        normalized.append(row)

    stale = [
        key
        for key, row in _registry.items()
        if row.get("source") == source and key not in incoming_keys
    ]
    for key in stale:
        del _registry[key]

    return normalized


def remove_position(*, account: str | None, ticker: str) -> None:
    key = _position_key(account, ticker)
    _registry.pop(key, None)


def list_positions() -> list[dict[str, Any]]:
    rows = list(_registry.values())
    rows.sort(key=lambda row: (row.get("ticker") or "", row.get("account") or ""))
    return rows


def clear_registry() -> None:
    _registry.clear()


def _to_float(value: Any) -> float | None:
    if value is None or value == "":
        return None
    try:
        return float(value)
    except (TypeError, ValueError):
        return None
