"""Auth and transport for the LooperPro MCP server.

Token resolution order:
  1. ~/.mcp-cli/tokens.json   (dedicated Looper CLI token, freshest)
  2. ~/.code_puppy/puppy.cfg  (Code Puppy marketplace / puppy token)
"""
import base64
import json
import sys
import time
from pathlib import Path
from typing import Any

import requests

MCP_URL = "https://looperpro-mcp-server.prod.walmart.com/mcp"
CDC_BASE = (
    "https://cdc-obj-200.storage.cloud.wal-mart.com/swift/v1/"
    "looperpro-generic-prod/reports"
)


# ---------------------------------------------------------------------------
# Token readers
# ---------------------------------------------------------------------------

def _read_mcp_cli_token() -> str | None:
    """Read a valid access token from ~/.mcp-cli/tokens.json."""
    tokens_path = Path.home() / ".mcp-cli" / "tokens.json"
    if not tokens_path.exists():
        return None
    try:
        data = json.loads(tokens_path.read_text())
        token = data.get("access_token")
        if not token:
            return None
        expires_at = data.get("expires_at")
        if expires_at:
            from datetime import datetime, timezone
            try:
                exp_dt = datetime.fromisoformat(expires_at)
                if exp_dt < datetime.now(timezone.utc):
                    print(
                        "Warning: ~/.mcp-cli/tokens.json expired. "
                        "Re-authenticate with: mcp-cli auth login",
                        file=sys.stderr,
                    )
                    return None
            except (ValueError, TypeError):
                pass
        return token
    except (json.JSONDecodeError, OSError):
        return None


def _read_puppy_cfg_token() -> str | None:
    """Read a valid token from ~/.code_puppy/puppy.cfg.

    Tries marketplace_token first, falls back to puppy_token.
    """
    cfg_path = Path.home() / ".code_puppy" / "puppy.cfg"
    if not cfg_path.exists():
        return None

    tokens: dict[str, str] = {}
    for line in cfg_path.read_text().splitlines():
        for key in ("marketplace_token", "puppy_token"):
            if line.startswith(key):
                tokens[key] = line.split("=", 1)[1].strip()

    for key in ("marketplace_token", "puppy_token"):
        token = tokens.get(key)
        if not token:
            continue
        try:
            payload_b64 = token.split(".")[1]
            payload_b64 += "=" * (4 - len(payload_b64) % 4)
            payload = json.loads(base64.urlsafe_b64decode(payload_b64))
            if payload.get("exp", 0) > time.time():
                return token
        except Exception:  # noqa: BLE001
            continue

    return tokens.get("marketplace_token") or tokens.get("puppy_token") or None


def get_token() -> str:
    """Return a valid bearer token for Looper MCP, or exit with a clear error."""
    token = _read_mcp_cli_token()
    if token:
        return token
    token = _read_puppy_cfg_token()
    if token:
        return token
    print(
        "Error: No valid token found. Tried:\n"
        "  1. ~/.mcp-cli/tokens.json\n"
        "  2. ~/.code_puppy/puppy.cfg\n"
        "Re-authenticate: mcp-cli auth login   or   /set marketplace_token",
        file=sys.stderr,
    )
    sys.exit(1)


# ---------------------------------------------------------------------------
# MCP transport  (requests replaces curl)
# ---------------------------------------------------------------------------

def mcp_call(tool_name: str, arguments: dict[str, Any]) -> dict:
    """Invoke a tool on the Looper MCP server via Streamable HTTP."""
    token = get_token()
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {"name": tool_name, "arguments": arguments},
    }
    try:
        resp = requests.post(
            MCP_URL,
            json=payload,
            headers={
                "Content-Type": "application/json",
                "Accept": "application/json, text/event-stream",
                "Authorization": f"Bearer {token}",
            },
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as exc:
        print(f"MCP HTTP error: {exc}", file=sys.stderr)
        sys.exit(1)

    if data.get("result", {}).get("isError"):
        error_text = data["result"]["content"][0]["text"]
        print(f"MCP Error: {error_text[:500]}", file=sys.stderr)
        sys.exit(1)

    if "error" in data:
        err_str = str(data["error"])
        if "invalid_token" in err_str:
            print(
                "Error: Token rejected by Looper MCP. "
                "Run: mcp-cli auth login  (or /set marketplace_token in Code Puppy)",
                file=sys.stderr,
            )
            sys.exit(1)
        if "missing_token" in err_str:
            print("Error: No bearer token was sent to Looper MCP.", file=sys.stderr)
            sys.exit(1)

    return data


def extract_json_block(text: str) -> dict | list | None:
    """Extract the first JSON code block from an MCP markdown response."""
    import re
    match = re.search(r"```(?:json)?\s*([\[\{].*?[\]\}])\s*```", text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    return None


# ---------------------------------------------------------------------------
# HTTP helper  (requests replaces curl)
# ---------------------------------------------------------------------------

def http_get(url: str, timeout: int = 10) -> str | None:
    """Fetch a URL and return its text body, or None on any error."""
    try:
        resp = requests.get(url, timeout=timeout)
        if resp.status_code != 200:
            return None
        return resp.text
    except requests.RequestException:
        return None


def http_head_ok(url: str, timeout: int = 5) -> bool:
    """Return True if a HEAD (or GET) request to *url* returns HTTP 200."""
    try:
        resp = requests.head(url, timeout=timeout, allow_redirects=True)
        return resp.status_code == 200
    except requests.RequestException:
        return False
