"""Claude Code integration helpers for Skills

This module provides convenience functions for Claude Code to use when
working with AgentSociety skills. These functions bridge the gap between
the skill scripts (which handle validation) and Claude Code (which handles
coding/implementation in the main loop).
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple

from agentsociety2.logger import get_logger

logger = get_logger()


def suggest_modules_for_topic(topic: str) -> Dict[str, Any]:
    """Suggest appropriate agent and environment modules for a research topic

    This function analyzes the research topic and suggests suitable
    agent types and environment modules based on keywords and common patterns.

    Args:
        topic: Research topic or description

    Returns:
        Dictionary with suggested modules and rationale
    """
    from agentsociety2.skills.experiment.module_discovery import (
        get_available_agent_modules,
        get_available_env_modules,
    )

    topic_lower = topic.lower()

    # Default suggestions
    suggested_agents = ["person_agent"]
    suggested_envs = ["simple_social_space"]
    rationale = []

    # Analyze topic for keywords
    keywords = {
        # Social/interaction topics
        "social": (["person_agent"], ["simple_social_space", "global_information"]),
        "interaction": (["person_agent"], ["simple_social_space"]),
        "communication": (["person_agent"], ["simple_social_space", "global_information"]),
        "information": (["person_agent"], ["global_information", "simple_social_space"]),
        "influence": (["person_agent"], ["simple_social_space", "global_information"]),
        "network": (["person_agent"], ["simple_social_space", "global_information"]),

        # Economic topics
        "economic": (["llm_donor_agent"], ["economy_space"]),
        "money": (["llm_donor_agent"], ["economy_space"]),
        "donat": (["llm_donor_agent"], ["economy_space", "reputation_game"]),
        "trade": (["llm_donor_agent"], ["economy_space"]),

        # Game theory topics
        "prisoner": (["prisoners_dilemma_agent"], ["prisoners_dilemma"]),
        "dilemma": (["prisoners_dilemma_agent"], ["prisoners_dilemma"]),
        "public good": (["public_goods_agent"], ["public_goods"]),
        "commons": (["commons_tragedy_agent"], ["commons_tragedy"]),
        "trust": (["trust_game_agent"], ["trust_game"]),
        "volunteer": (["volunteer_dilemma_agent"], ["volunteer_dilemma"]),

        # Mobility topics
        "mobility": (["person_agent"], ["mobility_space", "simple_social_space"]),
        "movement": (["person_agent"], ["mobility_space"]),
        "location": (["person_agent"], ["mobility_space"]),

        # Social media topics
        "social media": (["person_agent"], ["social_media"]),
        "platform": (["person_agent"], ["social_media"]),
        "post": (["person_agent"], ["social_media"]),
    }

    # Check for matching keywords
    for keyword, (agents, envs) in keywords.items():
        if keyword in topic_lower:
            suggested_agents = list(set(suggested_agents + agents))
            suggested_envs = list(set(suggested_envs + envs))
            rationale.append(f"Keyword '{keyword}' detected")

    # Get available modules
    available_agents = get_available_agent_modules()
    available_envs = get_available_env_modules()

    # Filter to only available modules
    suggested_agents = [a for a in suggested_agents if a in available_agents]
    suggested_envs = [e for e in suggested_envs if e in available_envs]

    # Build rationale
    if not rationale:
        rationale.append("Using default modules for general social simulation")
    else:
        rationale = [f"Suggestions based on: {', '.join(rationale)}"]

    return {
        "suggested_agents": suggested_agents,
        "suggested_envs": suggested_envs,
        "rationale": rationale,
        "available_agents": list(available_agents.keys()),
        "available_envs": list(available_envs.keys()),
    }


def generate_hypothesis_config(
    topic: str,
    description: str,
    rationale: str,
    groups: List[Dict[str, Any]],
    agent_classes: Optional[List[str]] = None,
    env_modules: Optional[List[str]] = None,
) -> Dict[str, Any]:
    """Generate a complete hypothesis configuration

    This function creates a properly formatted hypothesis configuration
    that can be passed to add_hypothesis_with_validation().

    Args:
        topic: Research topic
        description: Hypothesis description
        rationale: Theoretical basis
        groups: List of experiment groups
        agent_classes: Agent types (optional, will suggest if not provided)
        env_modules: Environment modules (optional, will suggest if not provided)

    Returns:
        Complete hypothesis configuration dictionary
    """
    # Suggest modules if not provided
    if not agent_classes or not env_modules:
        suggestions = suggest_modules_for_topic(topic + " " + description)
        if not agent_classes:
            agent_classes = suggestions["suggested_agents"]
        if not env_modules:
            env_modules = suggestions["suggested_envs"]

    return {
        "topic": topic,
        "hypothesis": {
            "description": description,
            "rationale": rationale,
        },
        "groups": groups,
        "agent_classes": agent_classes,
        "env_modules": env_modules,
    }


def validate_experiment_ready(
    workspace_path: Path,
    hypothesis_id: str,
    experiment_id: str,
) -> Tuple[bool, List[str], Dict[str, Any]]:
    """Check if an experiment is ready to run

    This function validates that all necessary configuration is in place
    for an experiment to be executed.

    Args:
        workspace_path: Path to workspace directory
        hypothesis_id: Hypothesis ID
        experiment_id: Experiment ID

    Returns:
        Tuple of (is_ready, missing_items, context)
    """
    from agentsociety2.skills.experiment.config import (
        get_experiment_paths,
        read_sim_settings,
    )

    missing = []
    context = {
        "hypothesis_id": hypothesis_id,
        "experiment_id": experiment_id,
        "has_config": False,
        "has_agents": False,
        "has_env_args": False,
    }

    paths = get_experiment_paths(workspace_path, hypothesis_id, experiment_id)

    # Check if hypothesis exists
    if not paths["hypothesis"].exists():
        missing.append(f"Hypothesis directory not found: {paths['hypothesis']}")
        return False, missing, context

    # Check if experiment directory exists
    if not paths["experiment"].exists():
        missing.append(f"Experiment directory not found: {paths['experiment']}")
        return False, missing, context

    # Read SIM_SETTINGS
    sim_settings = read_sim_settings(paths["hypothesis"])
    agent_classes = sim_settings.get("agentClasses", [])
    env_modules = sim_settings.get("envModules", [])

    if not agent_classes:
        missing.append("No agent classes selected in SIM_SETTINGS.json")
    else:
        context["has_agents"] = True

    if not env_modules:
        missing.append("No environment modules selected in SIM_SETTINGS.json")
    else:
        context["has_env_args"] = True

    # Check for init config
    if paths["init_config"].exists():
        context["has_config"] = True
    else:
        missing.append("init_config.json not found - run init action first")

    context["sim_settings"] = sim_settings
    context["agent_classes"] = agent_classes
    context["env_modules"] = env_modules

    is_ready = len(missing) == 0
    return is_ready, missing, context


def get_experiment_template(
    workspace_path: Path,
    hypothesis_id: str,
    experiment_id: str,
) -> Dict[str, Any]:
    """Get a template for experiment configuration

    This function provides a template structure that Claude Code can
    use to generate the full experiment configuration.

    Args:
        workspace_path: Path to workspace directory
        hypothesis_id: Hypothesis ID
        experiment_id: Experiment ID

    Returns:
        Template dictionary with structure to fill in
    """
    from agentsociety2.skills.experiment.config import (
        get_experiment_paths,
        read_sim_settings,
        read_experiment_info,
    )

    paths = get_experiment_paths(workspace_path, hypothesis_id, experiment_id)

    # Read SIM_SETTINGS
    sim_settings = read_sim_settings(paths["hypothesis"])
    agent_classes = sim_settings.get("agentClasses", [])
    env_modules = sim_settings.get("envModules", [])

    # Read experiment info
    exp_info = read_experiment_info(paths["experiment"])

    # Build template
    template = {
        "hypothesis_id": hypothesis_id,
        "experiment_id": experiment_id,
        "agent_classes": agent_classes,
        "env_modules": env_modules,
        "experiment_info": exp_info,
        "configuration": {
            "num_agents": 10,
            "num_steps": 20,
            "env_args": {},
            "agent_args": [],
        },
        "instructions": {
            "env_args": f"Configure environment parameters for: {', '.join(env_modules)}",
            "agent_args": f"Create {10} agent configurations with profile.custom_fields",
            "num_agents": "Should match the length of agent_args list",
        },
    }

    return template


def format_module_suggestion_message(suggestions: Dict[str, Any]) -> str:
    """Format module suggestions into a helpful message

    Args:
        suggestions: Dictionary from suggest_modules_for_topic()

    Returns:
        Formatted message string
    """
    lines = []
    lines.append("# Suggested Modules")
    lines.append("")
    lines.append("## Agent Types")
    for agent in suggestions["suggested_agents"]:
        lines.append(f"- `{agent}`")
    lines.append("")
    lines.append("## Environment Modules")
    for env in suggestions["suggested_envs"]:
        lines.append(f"- `{env}`")
    lines.append("")
    lines.append("## Rationale")
    for reason in suggestions["rationale"]:
        lines.append(f"- {reason}")
    lines.append("")
    lines.append("## All Available Modules")
    lines.append("")
    lines.append("### Agent Types")
    for agent in suggestions["available_agents"]:
        status = " [SUGGESTED]" if agent in suggestions["suggested_agents"] else ""
        lines.append(f"- `{agent}`{status}")
    lines.append("")
    lines.append("### Environment Modules")
    for env in suggestions["available_envs"]:
        status = " [SUGGESTED]" if env in suggestions["suggested_envs"] else ""
        lines.append(f"- `{env}`{status}")

    return "\n".join(lines)


__all__ = [
    "suggest_modules_for_topic",
    "generate_hypothesis_config",
    "validate_experiment_ready",
    "get_experiment_template",
    "format_module_suggestion_message",
]
