"""
System Prompt Assembly

Assembles comprehensive system prompts for different agents and providers.
Inspired by OpenCode's approach to provider-specific, behavior-rich prompts.
"""

import os
from pathlib import Path
from typing import Optional

# Get the directory containing the prompt files
PROMPTS_DIR = Path(__file__).parent

# Load prompt files
def _load_prompt(filename: str) -> str:
    """Load a prompt file from the prompts directory."""
    filepath = PROMPTS_DIR / filename
    if filepath.exists():
        return filepath.read_text(encoding="utf-8").strip()
    return ""

# Cache loaded prompts
_prompt_cache: dict[str, str] = {}

def _get_prompt(filename: str) -> str:
    """Get a prompt file, using cache."""
    if filename not in _prompt_cache:
        _prompt_cache[filename] = _load_prompt(filename)
    return _prompt_cache[filename]


# Main prompt files
PROMPT_ANTHROPIC = _get_prompt("anthropic.txt")
PROMPT_AGENTIC = _get_prompt("agentic.txt")
PROMPT_PLAN = _get_prompt("plan.txt")
PROMPT_EXPLORE = _get_prompt("explore.txt")


def get_provider_prompt(provider_id: str, model_id: str = "") -> str:
    """
    Get the appropriate system prompt for a provider/model combination.

    Args:
        provider_id: Provider identifier (anthropic, openai, google, etc.)
        model_id: Model identifier for provider-specific tuning

    Returns:
        System prompt string
    """
    # Claude models get the main anthropic prompt
    if "anthropic" in provider_id.lower() or "claude" in model_id.lower():
        return PROMPT_ANTHROPIC

    # GPT models with high capability get the agentic prompt
    if "openai" in provider_id.lower():
        if any(x in model_id.lower() for x in ["gpt-4o", "gpt-4-turbo", "o1", "o3"]):
            return PROMPT_AGENTIC
        return PROMPT_ANTHROPIC  # Use anthropic as default (well-structured)

    # Gemini models
    if "google" in provider_id.lower() or "gemini" in model_id.lower():
        return PROMPT_ANTHROPIC

    # Default to anthropic prompt (most comprehensive)
    return PROMPT_ANTHROPIC


def get_agent_prompt(agent_name: str) -> str:
    """
    Get the system prompt for a specific agent type.

    Args:
        agent_name: Agent name (build, plan, explore, etc.)

    Returns:
        Agent-specific prompt string
    """
    agent_name = agent_name.lower()

    if agent_name == "plan":
        return PROMPT_PLAN
    elif agent_name == "explore":
        return PROMPT_EXPLORE
    elif agent_name == "build":
        return PROMPT_AGENTIC
    else:
        return ""


def build_system_prompt(
    provider_id: str = "anthropic",
    model_id: str = "",
    agent_name: str = "build",
    project_path: Optional[Path] = None,
    include_environment: bool = True,
    custom_instructions: Optional[str] = None,
) -> list[str]:
    """
    Build a complete system prompt for an agent session.

    Args:
        provider_id: LLM provider identifier
        model_id: Model identifier
        agent_name: Agent type (build, plan, explore)
        project_path: Project root path for environment info
        include_environment: Whether to include environment context
        custom_instructions: Additional custom instructions

    Returns:
        List of system prompt sections
    """
    prompts = []

    # 1. Provider-specific base prompt
    base_prompt = get_provider_prompt(provider_id, model_id)
    if base_prompt:
        prompts.append(base_prompt)

    # 2. Agent-specific prompt
    agent_prompt = get_agent_prompt(agent_name)
    if agent_prompt:
        prompts.append(agent_prompt)

    # 3. Environment information
    if include_environment and project_path:
        env_info = _build_environment_info(project_path)
        if env_info:
            prompts.append(env_info)

    # 4. Custom instructions from project
    if project_path:
        project_instructions = _load_project_instructions(project_path)
        if project_instructions:
            prompts.append(project_instructions)

    # 5. Additional custom instructions
    if custom_instructions:
        prompts.append(custom_instructions)

    return prompts


def _build_environment_info(project_path: Path) -> str:
    """Build environment information string."""
    import subprocess
    from datetime import date
    import platform

    is_git = (project_path / ".git").exists()

    lines = [
        "Here is useful information about the environment you are running in:",
        "<env>",
        f"  Working directory: {project_path}",
        f"  Is directory a git repo: {'Yes' if is_git else 'No'}",
        f"  Platform: {platform.system().lower()}",
        f"  Today's date: {date.today().isoformat()}",
        "</env>",
    ]

    return "\n".join(lines)


def _load_project_instructions(project_path: Path) -> str:
    """Load project-specific instructions from config files."""
    # Check for various instruction files in order of preference
    instruction_files = [
        project_path / "CLAUDE.md",
        project_path / "AGENTS.md",
        project_path / ".groknroll" / "instructions.md",
        project_path / ".groknroll" / "AGENTS.md",
    ]

    for filepath in instruction_files:
        if filepath.exists():
            try:
                content = filepath.read_text(encoding="utf-8").strip()
                if content:
                    return f"Instructions from: {filepath.name}\n\n{content}"
            except Exception:
                pass

    return ""


def get_tool_usage_reminder() -> str:
    """Get a reminder about tool usage best practices."""
    return """
# Tool Usage Reminders
- Use Read tool instead of cat/head/tail for reading files
- Use Edit tool instead of sed/awk for editing files
- Use Grep tool instead of grep command for searching
- Use Glob tool instead of find command for finding files
- Run independent tool calls in parallel when possible
- Always read a file before editing it
"""


def get_code_quality_reminder() -> str:
    """Get a reminder about code quality expectations."""
    return """
# Code Quality
- Keep changes minimal and focused
- Follow existing code patterns and conventions
- Don't add unnecessary abstractions or features
- Don't refactor unrelated code
- Test your changes when possible
"""
