"""Tool tier definitions for different model capabilities.

Defines three tiers of MCP tools for use with language models of varying
capability.  Weaker models get fewer, simpler tools to avoid overwhelming
their context window and function-calling accuracy.  Stronger models get
the full set.

Tiers
-----
``essential``
    16 core tools for weak models (Llama, Mistral, Phi, Qwen).
``standard``
    ~50 tools for capable models (GPT-4o-mini, Gemini Flash, Command R+).
``full``
    ~160 curated tools for strong models (Claude, GPT-4, Gemini Pro).
``all``
    Every registered tool (includes plugin-contributed tools not in other tiers).
"""

from __future__ import annotations

# ---------------------------------------------------------------------------
# Tier definitions
# ---------------------------------------------------------------------------

TIER_ESSENTIAL: list[str] = [
    "printer_status",
    "printer_files",
    "upload_file",
    "start_print",
    "cancel_print",
    "pause_print",
    "resume_print",
    "set_temperature",
    "preflight_check",
    "send_gcode",
    "fleet_status",
    "submit_job",
    "job_status",
    "queue_summary",
    "kiln_health",
    "check_my_tier",
]

TIER_STANDARD: list[str] = TIER_ESSENTIAL + [
    # Marketplace & models
    "search_all_models",
    "download_model",
    "download_and_upload",
    "model_details",
    "marketplace_info",
    # Slicing
    "slice_model",
    "slice_and_print",
    "find_slicer",
    # Cost & materials
    "estimate_cost",
    "list_materials",
    "set_material",
    "get_material",
    "check_material_match",
    # Monitoring
    "printer_snapshot",
    "webcam_stream",
    # Fleet management
    "discover_printers",
    "register_printer",
    # Validation
    "validate_gcode",
    "validate_gcode_safe",
    # Original design & generation
    "generate_model",
    "generate_original_design",
    "download_generated_model",
    "await_generation",
    "validate_generated_mesh",
    "analyze_design_requirements",
    "build_generation_prompt",
    "audit_original_design",
    "validate_design_for_requirements",
    "analyze_printability",
    "auto_orient_model",
    "recommend_adhesion_settings",
    "analyze_generation_feedback",
    "improve_generation_prompt",
    # Workflow helpers
    "await_print_completion",
    "compare_print_options",
    # Safety profiles
    "list_safety_profiles",
    "get_safety_profile",
    # Safety audit
    "safety_audit",
    "safety_status",
    # History & stats
    "print_history",
    "printer_stats",
    # File & job management
    "delete_file",
    "job_history",
    "cancel_job",
    # Onboarding
    "get_started",
]

TIER_FULL: list[str] = [
    # --- Core printer control ---
    "printer_status",
    "printer_files",
    "upload_file",
    "delete_file",
    "start_print",
    "cancel_print",
    "pause_print",
    "resume_print",
    "set_temperature",
    "preflight_check",
    "send_gcode",
    "validate_gcode",
    # --- Fleet ---
    "fleet_status",
    "register_printer",
    "discover_printers",
    # --- Job queue ---
    "submit_job",
    "job_status",
    "queue_summary",
    "cancel_job",
    "job_history",
    # --- Events ---
    "recent_events",
    # --- Tier diagnostic ---
    "check_my_tier",
    # --- Billing ---
    "billing_summary",
    "billing_setup_url",
    "billing_status",
    "billing_history",
    # --- Marketplace ---
    "search_all_models",
    "marketplace_info",
    "search_models",
    "model_details",
    "model_files",
    "download_model",
    "download_and_upload",
    "browse_models",
    "list_model_categories",
    # --- Slicing ---
    "slice_model",
    "find_slicer",
    "slice_and_print",
    # --- Monitoring & snapshots ---
    "printer_snapshot",
    "webcam_stream",
    # --- Cost estimation ---
    "estimate_cost",
    # --- Materials ---
    "list_materials",
    "set_material",
    "get_material",
    "check_material_match",
    "list_spools",
    "add_spool",
    "remove_spool",
    # --- Bed leveling ---
    "bed_level_status",
    "trigger_bed_level",
    "set_leveling_policy",
    # --- Cloud sync ---
    "cloud_sync_status",
    "cloud_sync_now",
    "cloud_sync_configure",
    # --- Plugins ---
    "list_plugins",
    "plugin_info",
    # --- Fulfillment ---
    "fulfillment_materials",
    "fulfillment_quote",
    "save_shipping_profile",
    "list_shipping_profiles",
    "delete_shipping_profile",
    "issue_shipping_confirmation_token",
    "fulfillment_order",
    "fulfillment_order_status",
    "fulfillment_cancel",
    # --- Health ---
    "kiln_health",
    # --- Webhooks ---
    "register_webhook",
    "list_webhooks",
    "delete_webhook",
    # --- Workflow helpers ---
    "await_print_completion",
    "compare_print_options",
    "analyze_print_failure",
    "validate_print_quality",
    # --- Generation ---
    "list_generation_providers",
    "generate_model",
    "generate_original_design",
    "generation_status",
    "download_generated_model",
    "await_generation",
    "generate_and_print",
    "validate_generated_mesh",
    "analyze_printability",
    "auto_orient_model",
    "estimate_supports",
    "recommend_adhesion_settings",
    "diagnose_mesh",
    "analyze_generation_feedback",
    "improve_generation_prompt",
    # --- Original design intelligence ---
    "analyze_design_requirements",
    "build_generation_prompt",
    "audit_original_design",
    "get_material_design_profile",
    "list_design_materials",
    "recommend_design_material",
    "estimate_structural_load",
    "check_material_environment",
    "get_printer_design_capabilities",
    "list_printer_design_profiles",
    "get_design_template_info",
    "list_design_templates_catalog",
    "find_design_templates",
    "match_design_requirements",
    "validate_design_for_requirements",
    # --- Firmware ---
    "firmware_status",
    "update_firmware",
    "rollback_firmware",
    # --- Print history & stats ---
    "print_history",
    "printer_stats",
    "annotate_print",
    # --- Vision monitoring ---
    "monitor_print_vision",
    "watch_print",
    # --- Cross-printer learning ---
    "record_print_outcome",
    "get_printer_insights",
    "suggest_printer_for_job",
    # --- Agent memory ---
    "save_agent_note",
    "get_agent_context",
    "delete_agent_note",
    # --- Safety profiles ---
    "list_safety_profiles",
    "get_safety_profile",
    "validate_gcode_safe",
    # --- Safety audit & dashboard ---
    "safety_audit",
    "safety_status",
    "confirm_action",
    "get_started",
    # --- Slicer profiles ---
    "list_slicer_profiles",
    "get_slicer_profile",
    # --- Printer intelligence ---
    "get_printer_intelligence",
    "get_material_recommendation",
    "troubleshoot_printer",
    # --- Pipelines ---
    "list_print_pipelines",
    "run_quick_print",
    "run_calibrate",
    "run_benchmark",
]

TIERS: dict[str, list[str]] = {
    "essential": TIER_ESSENTIAL,
    "standard": TIER_STANDARD,
    "full": TIER_FULL,
    # "all" is resolved dynamically in get_tier() — not a static list.
}


# ---------------------------------------------------------------------------
# Tier lookup
# ---------------------------------------------------------------------------


def get_tier(name: str) -> list[str]:
    """Return tool names for a tier.

    Args:
        name: Tier name — ``"essential"``, ``"standard"``, ``"full"``,
            or ``"all"`` (every registered tool, bypasses allowlist).

    Returns:
        List of tool name strings belonging to that tier.

    Raises:
        KeyError: If *name* is not a recognised tier.
    """
    if name == "all":
        # Dynamically return every tool registered on the MCP instance.
        # Lazy import to avoid circular dependency with tool_schema.
        from kiln.tool_schema import get_all_registered_tool_names

        return get_all_registered_tool_names()
    try:
        return TIERS[name]
    except KeyError:
        valid = sorted(set(TIERS) | {"all"})
        raise KeyError(f"Unknown tier {name!r}. Available tiers: {', '.join(valid)}") from None


# ---------------------------------------------------------------------------
# Model-to-tier suggestion
# ---------------------------------------------------------------------------

# Patterns are checked with str.startswith against the lowercased model name.
_FULL_PREFIXES = (
    "claude",
    "gpt-4o",
    "gpt-4-",
    "gpt-4",
    "gemini-pro",
    "gemini-1.5-pro",
    "gemini-2",
    "o1",
    "o3",
    "o4",
    "deepseek-v3",
    "deepseek-r1",
)

_STANDARD_PREFIXES = (
    "gpt-4o-mini",
    "gpt-3.5",
    "gemini-flash",
    "gemini-1.5-flash",
    "command-r",
    "command-r+",
    "deepseek-v2",
    "yi-",
)

_ESSENTIAL_PREFIXES = (
    "llama",
    "mistral",
    "mixtral",
    "phi",
    "qwen",
    "gemma",
    "tinyllama",
    "codellama",
    "vicuna",
    "openchat",
)


def suggest_tier(model_name: str) -> str:
    """Suggest a tool tier based on model name or ID.

    Matches against known model family prefixes.  Returns ``"standard"``
    as a safe default for unrecognised models.

    Args:
        model_name: Model name or OpenRouter model ID
            (e.g. ``"claude-3-opus"``, ``"meta-llama/llama-3-8b"``).

    Returns:
        Tier name string: ``"essential"``, ``"standard"``, or ``"full"``.
    """
    name = model_name.lower()

    # OpenRouter IDs look like "provider/model-name" — extract the model part.
    if "/" in name:
        name = name.split("/", 1)[1]

    # gpt-4o-mini must be checked before gpt-4o (more specific first).
    for prefix in _STANDARD_PREFIXES:
        if name.startswith(prefix):
            return "standard"

    for prefix in _FULL_PREFIXES:
        if name.startswith(prefix):
            return "full"

    for prefix in _ESSENTIAL_PREFIXES:
        if name.startswith(prefix):
            return "essential"

    # Unknown model — standard is a safe middle ground.
    return "standard"
