"""
error_events.py

Small structured error event sink:
- In-memory counters per (source, stage)
- JSONL event log (append-only)
- JSON counters snapshot for quick dashboard/debug fetch
"""

from __future__ import annotations

import json
import threading
import time
from pathlib import Path
from typing import Any, Dict

try:
    from Core import settings as config

    _STATE_DIR = Path(config.APP_RUNTIME_DIR)
    _LEGACY_STATE_DIR = Path(config.APP_DATA_DIR)
except Exception:
    _STATE_DIR = Path(__file__).resolve().parents[1] / "Data" / "Runtime"
    _LEGACY_STATE_DIR = Path(__file__).resolve().parents[1] / "Data"

_STATE_DIR.mkdir(parents=True, exist_ok=True)
_COUNTERS_PATH = _STATE_DIR / "error_counters.json"
_EVENTS_PATH = _STATE_DIR / "error_events.jsonl"
_LEGACY_COUNTERS_PATH = _LEGACY_STATE_DIR / "error_counters.json"

_LOCK = threading.Lock()
_COUNTERS: Dict[str, int] = {}
_LAST_EVENT_TS: Dict[str, float] = {}
_MIN_INTERVAL_SEC = 0.75


def _load_counters() -> Dict[str, int]:
    for candidate in (_COUNTERS_PATH, _LEGACY_COUNTERS_PATH):
        try:
            if candidate.exists():
                raw = json.loads(candidate.read_text(encoding="utf-8"))
                if isinstance(raw, dict):
                    out: Dict[str, int] = {}
                    for k, v in raw.items():
                        try:
                            out[str(k)] = int(v)
                        except Exception:
                            continue
                    return out
        except Exception:
            pass
    return {}


with _LOCK:
    _COUNTERS.update(_load_counters())


def record_error(source: str, stage: str, exc: Any = None, context: Dict[str, Any] | None = None) -> int:
    """
    Record one structured error event.
    Returns current counter value for this error key.
    """
    now = time.time()
    src = str(source or "unknown")
    stg = str(stage or "unknown")
    key = f"{src}:{stg}"
    msg = "" if exc is None else str(exc)
    payload = {
        "time": now,
        "source": src,
        "stage": stg,
        "message": msg,
        "context": context or {},
    }

    with _LOCK:
        count = _COUNTERS.get(key, 0) + 1
        _COUNTERS[key] = count
        payload["count"] = count

        # Throttle repetitive event writes for the same key.
        last = float(_LAST_EVENT_TS.get(key, 0.0))
        should_write_event = (now - last) >= _MIN_INTERVAL_SEC
        if should_write_event:
            _LAST_EVENT_TS[key] = now
            try:
                with _EVENTS_PATH.open("a", encoding="utf-8") as f:
                    f.write(json.dumps(payload, ensure_ascii=False) + "\n")
            except Exception:
                pass

        try:
            _COUNTERS_PATH.write_text(json.dumps(_COUNTERS, ensure_ascii=False, indent=2), encoding="utf-8")
        except Exception:
            pass

        return count


def get_error_counters() -> Dict[str, int]:
    with _LOCK:
        return dict(_COUNTERS)
