"""Load config + generated artifacts, compile graph, invoke/astream."""

import os
from pathlib import Path
from typing import Any

from langchain_core.messages import HumanMessage

from foremet.config.load import load_config
from foremet.agent.graph import build_graph


def _get_llm_api_key(provider: str) -> str | None:
    """Return the appropriate API key env var for the provider (or None for ollama)."""
    if provider == "openai":
        return os.environ.get("OPENAI_API_KEY")
    if provider == "anthropic":
        return os.environ.get("ANTHROPIC_API_KEY")
    if provider == "gemini":
        return os.environ.get("GOOGLE_API_KEY")
    if provider == "ollama":
        return None
    return os.environ.get("OPENAI_API_KEY")


def _load_generated_tools(output_dir: Path, base_url: str, auth_env_var: str) -> list:
    """Import get_tools from output_dir/tools_generated.py and return tools list."""
    import importlib.util
    path = output_dir / "tools_generated.py"
    if not path.exists():
        raise FileNotFoundError(f"Generated tools not found: {path}. Run 'foremet init' or 'foremet refresh'.")
    spec = importlib.util.spec_from_file_location("tools_generated", path)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod.get_tools(base_url, auth_env_var)


def _load_system_prompt(output_dir: Path) -> str:
    """Load SYSTEM_PROMPT from output_dir/prompt_generated.py."""
    import importlib.util
    path = output_dir / "prompt_generated.py"
    if not path.exists():
        raise FileNotFoundError(f"Generated prompt not found: {path}. Run 'foremet init' or 'foremet refresh'.")
    spec = importlib.util.spec_from_file_location("prompt_generated", path)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod.SYSTEM_PROMPT


def run_invoke(
    cwd: Path | None = None,
    message: str = "",
    api_key: str | None = None,
) -> dict[str, Any]:
    """Load config and generated agent, invoke once with message, return final state."""
    config = load_config(cwd)
    output_dir = Path(config.output_dir)
    if not output_dir.is_absolute():
        output_dir = (cwd or Path.cwd()) / output_dir
    tools = _load_generated_tools(output_dir, config.base_url, config.auth_env_var)
    system_prompt = _load_system_prompt(output_dir)
    api_key = api_key or _get_llm_api_key(config.llm_provider)
    graph = build_graph(
        system_prompt=system_prompt,
        tools=tools,
        llm_provider=config.llm_provider,
        model=config.model,
        api_key=api_key,
        ollama_base_url=os.environ.get("OLLAMA_BASE_URL"),
    )
    initial = {"messages": [HumanMessage(content=message)]}
    return graph.invoke(initial)


def run_astream(
    cwd: Path | None = None,
    message: str = "",
    api_key: str | None = None,
):
    """Load config and generated agent, stream events for one invocation."""
    config = load_config(cwd)
    output_dir = Path(config.output_dir)
    if not output_dir.is_absolute():
        output_dir = (cwd or Path.cwd()) / output_dir
    tools = _load_generated_tools(output_dir, config.base_url, config.auth_env_var)
    system_prompt = _load_system_prompt(output_dir)
    api_key = api_key or _get_llm_api_key(config.llm_provider)
    graph = build_graph(
        system_prompt=system_prompt,
        tools=tools,
        llm_provider=config.llm_provider,
        model=config.model,
        api_key=api_key,
        ollama_base_url=os.environ.get("OLLAMA_BASE_URL"),
    )
    initial = {"messages": [HumanMessage(content=message)]}
    return graph.astream(initial)
