"""Aria Structured Logging Library (KAR-220 Phase 1).

Zentraler JSON-Logger fuer alle Aria-Skills + Cron-Services.
Schreibt Append-only nach /root/aria/logs/aria.jsonl mit
Pflichtfeldern: ts, level, skill, event, correlation_id,
payload_hash, error, duration_ms.

Usage:
    from aria_logging import get_logger
    log = get_logger("aria-akp-ingest")
    log.event("ingest_start", videos=5)
    log.error("yt_dlp_failed", err="...", video_id="abc")
    with log.timed("transcript_fetch", video_id="abc"):
        do_work()
"""
from __future__ import annotations
import hashlib
import json
import os
import sys
import time
import traceback
import uuid
from contextlib import contextmanager
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

LOG_PATH = Path(os.environ.get("ARIA_LOG_PATH", "/root/aria/logs/aria.jsonl"))
LOG_PATH.parent.mkdir(parents=True, exist_ok=True)


def _payload_hash(payload: dict) -> str:
    if not payload:
        return ""
    raw = json.dumps(payload, sort_keys=True, default=str).encode()
    return hashlib.sha256(raw).hexdigest()[:16]


class AriaLogger:
    def __init__(self, skill: str, correlation_id: str | None = None) -> None:
        self.skill = skill
        self.correlation_id = correlation_id or str(uuid.uuid4())[:12]

    def _write(self, level: str, event: str, error: str = "", duration_ms: float | None = None, **payload: Any) -> None:
        record = {
            "ts": datetime.now(timezone.utc).isoformat(),
            "level": level,
            "skill": self.skill,
            "event": event,
            "correlation_id": self.correlation_id,
            "payload_hash": _payload_hash(payload),
            "error": error,
            "duration_ms": duration_ms,
        }
        if payload:
            record["payload"] = payload
        try:
            with LOG_PATH.open("a") as f:
                f.write(json.dumps(record, default=str) + "\n")
        except OSError as e:
            print(f"[aria-log] write failed: {e}", file=sys.stderr)

    def event(self, event: str, **payload: Any) -> None:
        self._write("info", event, **payload)

    def warn(self, event: str, **payload: Any) -> None:
        self._write("warn", event, **payload)

    def error(self, event: str, err: str = "", **payload: Any) -> None:
        self._write("error", event, error=err, **payload)

    def exception(self, event: str, **payload: Any) -> None:
        tb = traceback.format_exc()
        self._write("exception", event, error=tb, **payload)

    @contextmanager
    def timed(self, event: str, **payload: Any):
        t0 = time.monotonic()
        try:
            yield
        except Exception as e:
            duration = (time.monotonic() - t0) * 1000
            self._write("exception", event, error=str(e), duration_ms=duration, **payload)
            raise
        else:
            duration = (time.monotonic() - t0) * 1000
            self._write("info", event, duration_ms=duration, **payload)


def get_logger(skill: str, correlation_id: str | None = None) -> AriaLogger:
    return AriaLogger(skill, correlation_id)
