from __future__ import annotations

import os
from pathlib import Path
from typing import Any

from src.tools import run_tool_pipeline

ROOT = Path(__file__).resolve().parent.parent
ARTIFACTS = ROOT / "artifacts"
ARTIFACTS.mkdir(exist_ok=True)
MEMORIES_DIR = ROOT / "data" / "memories"
MEMORIES_DIR.mkdir(parents=True, exist_ok=True)

_DEEP_AGENT = None
_DEEP_AGENT_ERROR: str | None = None
_DEEP_AGENT_INITIALIZED = False


def plan_task(message: str) -> str:
    return (
        "# Plan\n"
        f"- request: {message}\n"
        "- stack: deepagents(create_deep_agent)\n"
        "- features: skills + long_term_memory + subagents + composite_backends\n"
        "- profile: langfuse_trace_analysis\n"
        "- mode: hybrid"
    )


def _resolve_deep_model():
    explicit = os.getenv("AGENT_DEEP_MODEL", "").strip()
    if explicit:
        return explicit

    if os.getenv("OPENAI_API_KEY", "").strip():
        return f"openai:{os.getenv('AGENT_OPENAI_MODEL', 'gpt-4o-mini')}"
    if os.getenv("ANTHROPIC_API_KEY", "").strip():
        return f"anthropic:{os.getenv('AGENT_ANTHROPIC_MODEL', 'claude-3-5-sonnet-latest')}"
    if os.getenv("GOOGLE_API_KEY", "").strip() or os.getenv("GEMINI_API_KEY", "").strip():
        return f"google_genai:{os.getenv('AGENT_GEMINI_MODEL', 'gemini-2.0-flash')}"

    openrouter_key = os.getenv("OPENROUTER_API_KEY", "").strip()
    if openrouter_key:
        try:
            from langchain.chat_models import init_chat_model
        except Exception:
            return None
        return init_chat_model(
            model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4o-mini"),
            model_provider="openai",
            api_key=openrouter_key,
            base_url=os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1"),
            temperature=0,
        )
    return None


def run_langfuse_lens_query(message: str) -> str:
    """Run Langfuse Lens query and return markdown analysis."""
    return run_tool_pipeline(message)


def _parse_csv(raw: str) -> list[str]:
    return [item.strip() for item in str(raw or "").split(",") if item.strip()]


def _memory_sources() -> list[str]:
    configured = _parse_csv(os.getenv("AGENT_DEEP_MEMORY_SOURCES", "").strip())
    if configured:
        return configured
    return ["/AGENTS.md", "/memories/AGENTS.md"]


def _skills_sources() -> list[str]:
    configured = _parse_csv(os.getenv("AGENT_DEEP_SKILLS_SOURCES", "").strip())
    if configured:
        return configured
    return ["/skills/"]


def _ensure_default_memory_file() -> None:
    memory_file = MEMORIES_DIR / "AGENTS.md"
    if memory_file.exists():
        return
    memory_file.write_text(
        (
            "# Long-term Memory (Langfuse Lens)\n\n"
            "- Store durable user/team preferences here.\n"
            "- Keep secrets/credentials out of this file.\n"
            "- Use concise bullet points for reusable operational patterns.\n"
        ),
        encoding="utf-8",
    )


def _build_backend():
    from deepagents.backends import CompositeBackend, FilesystemBackend

    workspace_backend = FilesystemBackend(root_dir=ROOT, virtual_mode=False)
    memory_backend = FilesystemBackend(root_dir=MEMORIES_DIR, virtual_mode=False)
    return CompositeBackend(default=workspace_backend, routes={"/memories/": memory_backend})


def _build_deep_agent():
    model = _resolve_deep_model()
    if not model:
        return (
            None,
            "LLM API key/model not configured for create_deep_agent. "
            "Set AGENT_DEEP_MODEL or one of OPENAI_API_KEY/ANTHROPIC_API_KEY/GOOGLE_API_KEY/GEMINI_API_KEY/OPENROUTER_API_KEY.",
        )

    try:
        from deepagents import create_deep_agent
    except Exception as exc:
        return None, f"deepagents import failed: {exc}"

    _ensure_default_memory_file()

    backend = _build_backend()
    skills = _skills_sources()
    memory = _memory_sources()
    subagents = [
        {
            "name": "lens-analysis-specialist",
            "description": "Use for Langfuse trace analytics, observability deep-dive, prompt engineering, and model comparison.",
            "system_prompt": (
                "You are Lens Analysis Specialist. "
                "Call `run_langfuse_lens_query` exactly once with the user's raw request. "
                "Return the tool output as-is. Do not invent data."
            ),
            "tools": [run_langfuse_lens_query],
        }
    ]

    system_prompt = (
        "You are Langfuse Lens orchestrator built on create_deep_agent. "
        "Delegate each user request to subagent `lens-analysis-specialist` via `task` tool. "
        "Return the delegated result directly."
    )

    try:
        agent = create_deep_agent(
            model=model,
            tools=[run_langfuse_lens_query],
            system_prompt=system_prompt,
            subagents=subagents,
            skills=skills,
            memory=memory,
            backend=backend,
            name="langfuse-lens-deep-agent",
        )
    except Exception as exc:
        return None, f"create_deep_agent failed: {exc}"

    return agent, None


def _get_deep_agent():
    global _DEEP_AGENT_INITIALIZED, _DEEP_AGENT, _DEEP_AGENT_ERROR
    if _DEEP_AGENT_INITIALIZED:
        return _DEEP_AGENT, _DEEP_AGENT_ERROR

    _DEEP_AGENT, _DEEP_AGENT_ERROR = _build_deep_agent()
    _DEEP_AGENT_INITIALIZED = True
    return _DEEP_AGENT, _DEEP_AGENT_ERROR


def _stringify_content(content: Any) -> str:
    if content is None:
        return ""
    if isinstance(content, str):
        return content.strip()
    if isinstance(content, list):
        chunks: list[str] = []
        for item in content:
            if isinstance(item, str):
                if item.strip():
                    chunks.append(item.strip())
                continue
            if isinstance(item, dict):
                text = str(item.get("text", "")).strip()
                if text:
                    chunks.append(text)
        return "\n".join(chunks).strip()
    return str(content).strip()


def _extract_agent_output(result: Any) -> str:
    messages = result.get("messages") if isinstance(result, dict) else getattr(result, "messages", None)
    if isinstance(messages, list):
        for msg in reversed(messages):
            role = ""
            if isinstance(msg, dict):
                role = str(msg.get("role") or msg.get("type") or "").lower()
                if role in {"assistant", "ai"}:
                    text = _stringify_content(msg.get("content"))
                    if text:
                        return text
            else:
                role = str(getattr(msg, "type", "") or getattr(msg, "role", "")).lower()
                if role in {"assistant", "ai"}:
                    text = _stringify_content(getattr(msg, "content", None))
                    if text:
                        return text
    return _stringify_content(result)


def run(message: str) -> str:
    plan = plan_task(message)
    (ARTIFACTS / "request.md").write_text(plan, encoding="utf-8")

    output: str
    agent, error = _get_deep_agent()
    if agent is None:
        output = (
            "Deep Agent initialization failed.\n"
            f"- reason: {error or 'unknown error'}\n"
            "- note: fallback pipeline has been intentionally disabled.\n"
        )
    else:
        try:
            result = agent.invoke({"messages": [{"role": "user", "content": message}]})
            output = _extract_agent_output(result) or "(Deep Agent returned empty output)"
        except Exception as exc:
            output = (
                "Deep Agent execution failed.\n"
                f"- reason: {exc}\n"
                "- note: fallback pipeline has been intentionally disabled.\n"
            )

    final = f"# Final Output\n{output}"
    (ARTIFACTS / "final.md").write_text(final, encoding="utf-8")
    return final
