"""
``requests`` library integration.

Monkey-patches ``requests.Session.send`` to capture outgoing HTTP
requests, record breadcrumbs, and detect slow / errored responses.
"""

import time
import traceback

from overcast_sdk.integrations import Integration, DidNotEnable
from overcast_sdk.utils import capture_internal, _originals, truncate
from overcast_sdk.scrubber import EventScrubber


class RequestsIntegration(Integration):
    identifier = "requests"

    @staticmethod
    def setup_once():
        try:
            import requests
        except ImportError:
            raise DidNotEnable("requests is not installed")

        _originals["requests_send"] = requests.Session.send

        def _patched_send(self, request, **kwargs):
            from overcast_sdk.client import get_client
            from overcast_sdk.scope import get_current_scope

            url = request.url
            method = request.method

            client = get_client()

            # Skip Overcast's own calls
            if client and client.options.get("base_url", "") in url:
                return _originals["requests_send"](self, request, **kwargs)

            start = time.monotonic()
            try:
                response = _originals["requests_send"](self, request, **kwargs)
                duration = time.monotonic() - start

                # Breadcrumb
                with capture_internal:
                    scope = get_current_scope()
                    scope.add_breadcrumb({
                        "type": "http",
                        "category": "requests",
                        "message": f"{method} {url}",
                        "data": {
                            "url": url,
                            "method": method,
                            "status_code": response.status_code,
                            "duration_ms": round(duration * 1000),
                        },
                        "level": "error" if response.status_code >= 500 else "info",
                    })

                if client:
                    meta = {
                        "type": "http_outgoing",
                        "method": method,
                        "url": url,
                        "status_code": response.status_code,
                        "duration_s": round(duration, 3),
                        "request_body": truncate(request.body),
                        "response_body": truncate(response.text),
                        "response_headers": EventScrubber.scrub_headers(
                            dict(response.headers)
                        ),
                    }
                    threshold = client.options.get("slow_request_threshold", 5.0)
                    if duration > threshold:
                        client.enqueue(
                            "WARNING",
                            f"Slow request: {method} {url} ({duration:.1f}s)",
                            {**meta, "type": "slow_http"},
                        )

                    if response.status_code >= 500:
                        client.enqueue(
                            "ERROR",
                            f"HTTP {response.status_code}: {method} {url}",
                            meta,
                        )
                    elif response.status_code >= 400:
                        client.enqueue(
                            "WARNING",
                            f"HTTP {response.status_code}: {method} {url}",
                            meta,
                        )
                    else:
                        client.enqueue(
                            "DEBUG",
                            f"HTTP {response.status_code}: {method} {url} ({duration:.1f}s)",
                            meta,
                        )
                return response

            except Exception as exc:
                duration = time.monotonic() - start
                with capture_internal:
                    scope = get_current_scope()
                    scope.add_breadcrumb({
                        "type": "http",
                        "category": "requests",
                        "message": f"{method} {url} (error)",
                        "data": {"url": url, "method": method, "error": str(exc)},
                        "level": "error",
                    })
                    if client:
                        client.enqueue("ERROR", f"HTTP error: {method} {url} — {exc}", {
                            "type": "http_network_error",
                            "method": method,
                            "url": url,
                            "duration_s": round(duration, 3),
                            "error": {
                                "type": type(exc).__name__,
                                "message": str(exc),
                                "traceback": traceback.format_exc(),
                            },
                        })
                raise

        requests.Session.send = _patched_send
