"""Structured error logger — writes JSON-line entries to a log file.

Errors are appended to logs/apex_errors.log so they are readable
without terminal access. The health endpoint exposes recent entries.
"""
import json
import logging
import os
import traceback
from datetime import datetime

logger = logging.getLogger("apex")

_DEFAULT_LOG_PATH = os.path.join("logs", "apex_errors.log")
_MAX_TAIL = 500  # max lines kept in the file before rotation


class StructuredErrorLogger:
    def __init__(self, log_file: str = _DEFAULT_LOG_PATH):
        self._log_file = log_file
        try:
            os.makedirs(os.path.dirname(os.path.abspath(log_file)), exist_ok=True)
        except Exception:
            pass

    def log_error(
        self,
        trace_id: str,
        error: Exception,
        path: str = "",
        method: str = "",
        extra: dict | None = None,
    ) -> None:
        entry = {
            "ts": datetime.utcnow().isoformat(),
            "trace_id": trace_id,
            "error_type": type(error).__name__,
            "message": str(error)[:500],
            "path": path,
            "method": method,
            "tb": traceback.format_exc()[-1000:],
            **(extra or {}),
        }
        try:
            with open(self._log_file, "a", encoding="utf-8") as f:
                f.write(json.dumps(entry, ensure_ascii=False) + "\n")
        except Exception as exc:
            logger.warning("StructuredErrorLogger write failed: %s", exc)

    def recent_errors(self, limit: int = 20) -> list[dict]:
        try:
            with open(self._log_file, "r", encoding="utf-8") as f:
                lines = f.readlines()
            entries = []
            for line in reversed(lines):
                line = line.strip()
                if not line:
                    continue
                try:
                    entries.append(json.loads(line))
                except Exception:
                    pass
                if len(entries) >= limit:
                    break
            return entries
        except FileNotFoundError:
            return []
        except Exception as exc:
            logger.warning("StructuredErrorLogger read failed: %s", exc)
            return []
