import os
import json
import datetime as dt
import logging
from pathlib import Path


def _debug_enabled() -> bool:
    for name in ("BG_AGENT_DEBUG", "DEBUG"):
        v = os.environ.get(name)
        if v and str(v).strip().lower() in {"1", "true", "yes", "on"}:
            return True
    return False


def _now_stamp() -> str:
    return dt.datetime.now().strftime("%Y%m%d-%H%M%S")


def _iso_now() -> str:
    return dt.datetime.now().isoformat(timespec="seconds")


def _join_url(base: str, endpoint: str) -> str:
    return f"{str(base).rstrip('/')}/{str(endpoint).lstrip('/')}"


def _redact(value: str) -> str:
    if not value:
        return value
    return "***REDACTED***"


def _write_json(path: str, data: dict) -> None:
    try:
        Path(os.path.dirname(path)).mkdir(parents=True, exist_ok=True)
        with open(path, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=None, separators=(",", ":"))
    except Exception as e:
        logging.debug("debug_http: failed to write %s: %s", path, e)


def chat_completion_with_logging(client, base_url: str, api_key: str, *, model: str, messages: list, app_dir: str, attempt: int) -> str:
    """Perform a chat.completions.create call and, if debug is enabled, write
    request/response JSON files containing URL, headers (sanitized), payload, and body.

    Returns the assistant text content.
    """
    # Build request
    payload = {"model": model, "messages": messages}

    if _debug_enabled():
        tag = f"{_now_stamp()}-chat_completions-attempt{attempt}"
        http_dir = os.path.join(app_dir, "http")
        req_path = os.path.join(http_dir, f"{tag}-request.json")
        req_headers = {
            "Authorization": _redact(f"Bearer {api_key}"),
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        _write_json(req_path, {
            "timestamp": _iso_now(),
            "attempt": attempt,
            "method": "POST",
            "url": _join_url(base_url, "/chat/completions"),
            "headers": req_headers,
            "payload": payload,
        })

    # Prefer raw response for headers/status when available, but keep it optional
    text = ""
    used_raw = False
    with_raw = None
    try:
        with_raw = getattr(getattr(client.chat.completions, "with_raw_response"), "create")
        used_raw = True
    except Exception:
        used_raw = False

    if used_raw and with_raw:
        raw = with_raw(**payload)
        http_resp = getattr(raw, "http_response", raw)
        try:
            body = http_resp.json()
        except Exception:
            try:
                body = json.loads(getattr(http_resp, "text", "") or "{}")
            except Exception:
                body = {"_note": "non-JSON response"}

        try:
            text = (
                body.get("choices", [{}])[0]
                .get("message", {})
                .get("content", "")
            )
        except Exception:
            text = ""

        if _debug_enabled():
            tag = f"{_now_stamp()}-chat_completions-attempt{attempt}"
            http_dir = os.path.join(app_dir, "http")
            resp_path = os.path.join(http_dir, f"{tag}-response.json")
            headers_dict = {}
            try:
                headers_dict = dict(getattr(http_resp, "headers", {}) or {})
            except Exception:
                headers_dict = {}
            _write_json(resp_path, {
                "timestamp": _iso_now(),
                "attempt": attempt,
                "status_code": getattr(http_resp, "status_code", None),
                "reason": getattr(http_resp, "reason_phrase", None),
                "headers": headers_dict,
                "body": body,
            })
        return text

    # Fallback: normal SDK call
    resp = client.chat.completions.create(**payload)
    try:
        text = resp.choices[0].message.content or ""
    except Exception:
        text = ""

    if _debug_enabled():
        tag = f"{_now_stamp()}-chat_completions-attempt{attempt}"
        http_dir = os.path.join(app_dir, "http")
        resp_path = os.path.join(http_dir, f"{tag}-response.json")
        body = None
        try:
            if hasattr(resp, "model_dump_json"):
                body = json.loads(resp.model_dump_json())
            elif hasattr(resp, "model_dump"):
                body = resp.model_dump(mode="python")  # type: ignore[arg-type]
            elif hasattr(resp, "to_dict"):
                body = resp.to_dict()
        except Exception:
            body = {"_note": "unable to serialize response model"}
        _write_json(resp_path, {"timestamp": _iso_now(), "attempt": attempt, "body": body})

    return text


def log_attempt_error(app_dir: str, attempt: int, error: Exception) -> None:
    if not _debug_enabled():
        return
    http_dir = os.path.join(app_dir, "http")
    tag = f"{_now_stamp()}-chat_completions-attempt{attempt}-error"
    err_path = os.path.join(http_dir, f"{tag}.json")
    _write_json(err_path, {
        "timestamp": _iso_now(),
        "attempt": attempt,
        "error": str(error),
        "type": getattr(type(error), "__name__", "Exception"),
    })

