"""Exception capture for unhandled exceptions."""

from __future__ import annotations

import sys
import threading
import traceback
from typing import List

from autodebug_probe.recorder import get_recorder


_original_excepthook = sys.excepthook
_original_threading_excepthook = getattr(threading, "excepthook", None)


def format_stack(tb) -> List[dict]:
    frames = []
    for frame in traceback.extract_tb(tb):
        frames.append({"file": frame.filename, "line": frame.lineno, "function": frame.name})
    return frames


def _hook(exc_type, exc, tb):
    payload = {
        "type": "EXCEPTION",
        "exc_type": getattr(exc_type, "__name__", str(exc_type)),
        "message": str(exc),
        "stack": format_stack(tb),
    }
    get_recorder().record_event(payload)
    _original_excepthook(exc_type, exc, tb)


def _threading_hook(args):
    payload = {
        "type": "EXCEPTION",
        "exc_type": getattr(args.exc_type, "__name__", str(args.exc_type)),
        "message": str(args.exc_value),
        "stack": format_stack(args.exc_traceback),
        "thread": args.thread.name if args.thread else None,
        "boundary": "THREAD",
    }
    get_recorder().record_event(payload)
    if _original_threading_excepthook:
        _original_threading_excepthook(args)


def install() -> None:
    sys.excepthook = _hook
    if hasattr(threading, "excepthook"):
        threading.excepthook = _threading_hook
