#!/usr/bin/env python3
"""
Commander Client — direct DeepSeek API caller for macro direction decisions.

Called by gold_trader._spawn_macro_direction_process() to get AI-driven
macro direction without depending on the openclaw CLI.
"""

import json
import os
import time
from typing import Any, Optional

import requests


def _get_api_key() -> str:
    api_key = os.environ.get("DEEPSEEK_API_KEY", "")
    if api_key:
        return api_key
    try:
        import config_manager
        app_config = config_manager.load_app_config()
        api_key = app_config.get("DEEPSEEK_API_KEY", "")
    except Exception:
        pass
    return api_key


def call_commander(
    session_data: Optional[dict] = None,
    structure_snapshot: Optional[dict] = None,
    current_regime: str = "UNKNOWN",
    vol_ratio: float = 1.0,
    current_position: Optional[dict] = None,
    force_refresh: bool = False,
) -> dict[str, Any]:
    """
    Call DeepSeek API to determine macro trading direction.

    Returns a dict with: direction, confidence, reason, degraded,
    conviction, timeframe, risk_appetite, macro_regime, key_levels,
    calibrated_confidence, updated_ts.
    """
    api_key = _get_api_key()
    if not api_key:
        return _fallback_response(session_data, "API key not configured")

    all_sessions = {}
    overall_score = 0.0
    overall_direction = "NEUTRAL"
    if isinstance(session_data, dict):
        all_sessions = session_data.get("all_sessions", {})
        overall_score = session_data.get("overall_score", 0.0)
        overall_direction = session_data.get("overall_direction", "NEUTRAL")

    pos_info = ""
    if isinstance(current_position, dict) and current_position:
        pos_info = f"\nCurrent Position: {json.dumps(current_position, default=str)}"

    prompt = f"""
You are the Commander (Macro Strategic Agent) for a Gold (XAUUSD) algorithmic trading system.
Your job is to determine the macro trading direction for the current market phase.

Session Data (EMA biases, RSI, Volatility, Direction):
{json.dumps(all_sessions, indent=2)}

Overall Technical Score: {overall_score} (Positive = BULLISH, Negative = BEARISH)
Overall Technical Direction: {overall_direction}

Market Structure Snapshot: {json.dumps(structure_snapshot or {}, default=str)}
Current Regime: {current_regime}
Volatility Ratio: {vol_ratio:.2f}{pos_info}

IMPORTANT: You are a LONG-ONLY macro strategist. You may only output LONG or NEUTRAL — never SHORT.
Provide your strategic direction (LONG or NEUTRAL), a confidence score (0.0 to 1.0),
a conviction level (low/medium/high), risk appetite (conservative/balanced/aggressive),
macro regime classification, and a concise reason.

Output exactly in JSON format:
{{
  "direction": "LONG",
  "confidence": 0.8,
  "reason": "...",
  "conviction": "medium",
  "risk_appetite": "balanced",
  "macro_regime": "bullish_trend",
  "timeframe": "H4",
  "key_levels": {{"support": 2900, "resistance": 3000}}
}}
"""

    try:
        resp = requests.post(
            "https://api.deepseek.com/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
            },
            json={
                "model": "deepseek-v4-flash",
                "messages": [
                    {"role": "system", "content": "You are a strategic macro commander for a gold trading system. Always output valid JSON only."},
                    {"role": "user", "content": prompt},
                ],
                "max_tokens": 600,
                "temperature": 0.5,
            },
            timeout=90,
        )
        resp.raise_for_status()
        data = resp.json()
        text = data["choices"][0]["message"]["content"].strip()

        # Extract JSON from response
        start_idx = text.find('{')
        end_idx = text.rfind('}')
        if start_idx != -1 and end_idx != -1:
            decision = json.loads(text[start_idx:end_idx+1])
        else:
            raise ValueError(f"No JSON found in response: {text[:200]}")

        direction = str(decision.get("direction", "LONG")).upper()
        if direction == "SHORT":
            direction = "LONG"

        return {
            "direction": direction,
            "confidence": float(decision.get("confidence", 0.5)),
            "reason": str(decision.get("reason", ""))[:300],
            "degraded": False,
            "conviction": decision.get("conviction"),
            "timeframe": decision.get("timeframe"),
            "risk_appetite": decision.get("risk_appetite", "balanced"),
            "macro_regime": decision.get("macro_regime", current_regime),
            "key_levels": decision.get("key_levels"),
            "calibrated_confidence": float(decision.get("confidence", 0.5)),
            "updated_ts": time.time(),
        }

    except Exception as e:
        print(f"[commander_client] API call failed: {e}")
        return _fallback_response(session_data, str(e))


def _fallback_response(session_data: Optional[dict], error: str) -> dict[str, Any]:
    """Degraded fallback based on technical signals."""
    overall_direction = "NEUTRAL"
    if isinstance(session_data, dict):
        overall_direction = session_data.get("overall_direction", "NEUTRAL")

    if overall_direction in ("BULLISH", "SLIGHTLY_BULLISH"):
        direction = "LONG"
    elif overall_direction in ("BEARISH", "SLIGHTLY_BEARISH"):
        direction = "NEUTRAL"
    else:
        direction = "LONG"

    return {
        "direction": direction,
        "confidence": 0.5,
        "reason": f"[Fallback] Technical: {overall_direction}. Error: {error[:100]}",
        "degraded": True,
        "conviction": "low",
        "timeframe": None,
        "risk_appetite": "conservative",
        "macro_regime": "UNKNOWN",
        "key_levels": None,
        "calibrated_confidence": 0.5,
        "updated_ts": time.time(),
    }
