"""
Enterprise MCP Tool definitions — CRM, ERP, Analytics, Marketplace, Onboarding.

Exports:
  ENTERPRISE_TOOLS    — list[Tool] to append to the main TOOLS list in server.py
  ENTERPRISE_HANDLERS — dict mapping tool name -> async handler function
"""

import asyncio
import json
from typing import Any

from mcp.types import TextContent, Tool, ToolAnnotations

_SAFE_WRITE = ToolAnnotations(
    readOnlyHint=False, destructiveHint=False,
    idempotentHint=False, openWorldHint=False,
)
_SAFE_READ = ToolAnnotations(
    readOnlyHint=True, destructiveHint=False,
    idempotentHint=True, openWorldHint=False,
)

# ── Tool Definitions ──────────────────────────────────────────────────────

ENTERPRISE_TOOLS: list[Tool] = [
    # ── CRM ───────────────────────────────────────────────────────────────
    Tool(
        name="broker_record_interaction",
        description=(
            "Record an interaction with another agent. Tracks communication "
            "history for relationship management across the swarm."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "target_session_id": {
                    "type": "string",
                    "description": "Session ID of the agent you interacted with.",
                },
                "interaction_type": {
                    "type": "string",
                    "description": "Type of interaction: message, task, review, hire, meeting.",
                    "default": "message",
                },
                "summary": {
                    "type": "string",
                    "description": "Brief summary of the interaction.",
                },
                "sentiment": {
                    "type": "string",
                    "description": "Interaction sentiment: positive, neutral, negative.",
                    "default": "neutral",
                },
                "channel": {
                    "type": "string",
                    "description": "Channel where the interaction occurred.",
                },
            },
            "required": ["target_session_id", "summary"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_get_relationship",
        description=(
            "View your relationship with a specific agent — interaction history, "
            "sentiment trend, and trust score."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "target_session_id": {
                    "type": "string",
                    "description": "Session ID of the agent to look up.",
                },
            },
            "required": ["target_session_id"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_list_relationships",
        description="List all agent relationships with interaction counts and trust scores.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_suggest_team",
        description=(
            "Suggest the best team of agents for a task based on skills, "
            "past collaboration history, and relationship strength."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "task_description": {
                    "type": "string",
                    "description": "Description of the task that needs a team.",
                },
                "required_skills": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Skills needed for the task.",
                },
                "team_size": {
                    "type": "integer",
                    "description": "Maximum number of agents to suggest.",
                    "default": 3,
                },
            },
            "required": ["task_description", "required_skills"],
        },
        annotations=_SAFE_READ,
    ),

    # ── ERP ───────────────────────────────────────────────────────────────
    Tool(
        name="broker_set_capacity",
        description=(
            "Set resource limits for your agent — max concurrent tasks, "
            "message rate, and availability windows."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "max_concurrent_tasks": {
                    "type": "integer",
                    "description": "Maximum tasks this agent can handle simultaneously.",
                },
                "max_messages_per_minute": {
                    "type": "integer",
                    "description": "Message rate limit per minute.",
                },
                "available_hours": {
                    "type": "string",
                    "description": "Availability window in UTC (e.g. '09:00-17:00').",
                },
            },
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_get_utilization",
        description=(
            "View agent utilization across the network — task load, message "
            "throughput, and capacity headroom per agent."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "session_id": {
                    "type": "string",
                    "description": "Agent session ID (omit for network-wide view).",
                },
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_allocate_resources",
        description=(
            "Allocate resources for a task — reserves capacity on the target "
            "agent and tracks the allocation lifecycle."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {
                    "type": "string",
                    "description": "Task ID to allocate resources for.",
                },
                "target_session_id": {
                    "type": "string",
                    "description": "Agent to allocate resources on.",
                },
                "units": {
                    "type": "integer",
                    "description": "Number of resource units to allocate.",
                    "default": 1,
                },
            },
            "required": ["task_id", "target_session_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_cost_report",
        description=(
            "Get a cost summary — resource consumption, task throughput, "
            "and efficiency metrics over a time window."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "period": {
                    "type": "string",
                    "description": "Time period: 1h, 6h, 24h, 7d.",
                    "default": "24h",
                },
                "session_id": {
                    "type": "string",
                    "description": "Filter by agent session ID (omit for all).",
                },
            },
        },
        annotations=_SAFE_READ,
    ),

    # ── Analytics ─────────────────────────────────────────────────────────
    Tool(
        name="broker_message_stats",
        description=(
            "Message throughput statistics — volume per channel, messages "
            "per agent, peak hours, and trend over time."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "channel": {
                    "type": "string",
                    "description": "Filter by channel (omit for all channels).",
                },
                "period": {
                    "type": "string",
                    "description": "Time period: 1h, 6h, 24h, 7d.",
                    "default": "24h",
                },
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_task_stats",
        description=(
            "Task completion metrics — success rate, average duration, "
            "throughput, and bottleneck analysis."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "period": {
                    "type": "string",
                    "description": "Time period: 1h, 6h, 24h, 7d.",
                    "default": "24h",
                },
                "session_id": {
                    "type": "string",
                    "description": "Filter by agent session ID (omit for all).",
                },
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_leaderboard",
        description=(
            "Ranked agent leaderboard — sorted by tasks completed, reputation, "
            "or message volume. Includes badges and streaks."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "sort_by": {
                    "type": "string",
                    "description": "Ranking metric: tasks, reputation, messages.",
                    "default": "tasks",
                },
                "limit": {
                    "type": "integer",
                    "description": "Number of agents to show.",
                    "default": 10,
                },
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_system_health",
        description=(
            "Overall system health — active sessions, stale agents, storage "
            "usage, message backlog, and error rates."
        ),
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),

    # ── Marketplace ───────────────────────────────────────────────────────
    Tool(
        name="broker_list_service",
        description=(
            "Publish a service offering to the marketplace. Other agents can "
            "browse and book your service."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Service name (e.g. 'Code Review', 'Test Suite Generation').",
                },
                "description": {
                    "type": "string",
                    "description": "Detailed description of the service offered.",
                },
                "category": {
                    "type": "string",
                    "description": "Service category: development, testing, review, documentation, devops.",
                },
                "estimated_duration": {
                    "type": "string",
                    "description": "Estimated time to deliver (e.g. '15m', '1h', '4h').",
                },
                "tags": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Searchable tags for the service.",
                },
            },
            "required": ["name", "description", "category"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_browse_services",
        description=(
            "Browse the service marketplace. Filter by category, tag, or "
            "provider. Shows ratings and availability."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "category": {
                    "type": "string",
                    "description": "Filter by category.",
                },
                "tag": {
                    "type": "string",
                    "description": "Filter by tag.",
                },
                "provider_session_id": {
                    "type": "string",
                    "description": "Filter by provider agent.",
                },
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_book_service",
        description=(
            "Book a service from the marketplace. Creates a task and notifies "
            "the provider."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "service_id": {
                    "type": "string",
                    "description": "ID of the service to book.",
                },
                "requirements": {
                    "type": "string",
                    "description": "Specific requirements or context for this booking.",
                },
                "channel": {
                    "type": "string",
                    "description": "Channel for delivery updates.",
                    "default": "marketplace",
                },
            },
            "required": ["service_id", "requirements"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_review_service",
        description=(
            "Leave a review after service delivery. Affects provider's "
            "marketplace rating and visibility."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "booking_id": {
                    "type": "string",
                    "description": "Booking ID from broker_book_service.",
                },
                "rating": {
                    "type": "number",
                    "description": "Rating 1-5.",
                },
                "review": {
                    "type": "string",
                    "description": "Written review of the service.",
                },
            },
            "required": ["booking_id", "rating"],
        },
        annotations=_SAFE_WRITE,
    ),

    # ── Onboarding ────────────────────────────────────────────────────────
    Tool(
        name="broker_add_knowledge",
        description=(
            "Add an entry to the shared knowledge base. New agents receive "
            "this during onboarding."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "topic": {
                    "type": "string",
                    "description": "Knowledge topic (e.g. 'project_structure', 'coding_standards').",
                },
                "content": {
                    "type": "string",
                    "description": "The knowledge content to store.",
                },
                "tags": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Tags for categorization and search.",
                },
            },
            "required": ["topic", "content"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_start_onboarding",
        description=(
            "Begin onboarding for a new agent. Returns a structured briefing "
            "with project context, active tasks, team members, and norms."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "target_session_id": {
                    "type": "string",
                    "description": "Session ID of the agent to onboard (omit for self).",
                },
                "role": {
                    "type": "string",
                    "description": "Expected role: developer, reviewer, tester, devops, general.",
                    "default": "general",
                },
            },
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_get_briefing",
        description=(
            "Get a project briefing — current state, active channels, recent "
            "decisions, open tasks, and team composition."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "scope": {
                    "type": "string",
                    "description": "Briefing scope: full, tasks, team, decisions.",
                    "default": "full",
                },
            },
        },
        annotations=_SAFE_READ,
    ),
]


# ── Handlers ──────────────────────────────────────────────────────────────


# -- CRM ------------------------------------------------------------------

async def _handle_record_interaction(args: dict) -> list[TextContent]:
    from .crm import record_interaction
    partner = args.get("target_session_id", "")
    if not partner:
        return [TextContent(type="text", text="Error: target_session_id is required")]
    entry = await asyncio.to_thread(
        record_interaction,
        partner_id=partner,
        partner_name=args.get("partner_name", ""),
        channel=args.get("channel", "general"),
        interaction_type=args.get("interaction_type", "message"),
    )
    return [TextContent(
        type="text",
        text=f"Interaction recorded with {partner}: {entry.get('interaction_count', 0)} total interactions",
    )]


async def _handle_get_relationship(args: dict) -> list[TextContent]:
    from .crm import get_relationship
    partner = args.get("target_session_id", "")
    if not partner:
        return [TextContent(type="text", text="Error: target_session_id is required")]
    rel = await asyncio.to_thread(get_relationship, partner_id=partner)
    if not rel:
        return [TextContent(type="text", text=f"No relationship data found for {partner}")]
    return [TextContent(type="text", text=json.dumps(rel, indent=2, default=str))]


async def _handle_list_relationships(args: dict) -> list[TextContent]:
    from .crm import list_relationships
    rels = await asyncio.to_thread(list_relationships)
    if not rels:
        return [TextContent(type="text", text="No relationships recorded yet.")]
    lines = []
    for r in rels:
        lines.append(
            f"  {r['target_session_id']}: {r['interaction_count']} interactions, "
            f"trust={r.get('trust_score', 'N/A')}"
        )
    return [TextContent(type="text", text="Agent relationships:\n" + "\n".join(lines))]


async def _handle_suggest_team(args: dict) -> list[TextContent]:
    from .crm import suggest_team
    skills = args.get("required_skills", [])
    if not skills:
        return [TextContent(type="text", text="Error: required_skills is required")]
    result = await asyncio.to_thread(
        suggest_team,
        required_skills=skills,
        team_size=args.get("team_size", 3),
    )
    team = result.get("team", [])
    if not team:
        return [TextContent(type="text", text="No suitable agents found for this team.")]
    lines = []
    for i, member in enumerate(team, 1):
        lines.append(
            f"  {i}. {member['session_id']} — score: {member.get('composite_score', 'N/A')}, "
            f"skills: {', '.join(member.get('skills_matched', []))}"
        )
    return [TextContent(type="text", text="Suggested team:\n" + "\n".join(lines))]


# -- ERP ------------------------------------------------------------------

async def _handle_set_capacity(args: dict) -> list[TextContent]:
    from .erp import set_capacity
    capacity = await asyncio.to_thread(
        set_capacity,
        max_concurrent_tasks=args.get("max_concurrent_tasks", 5),
        token_budget_per_hour=args.get("token_budget_per_hour", 100_000),
    )
    return [TextContent(
        type="text",
        text=(
            f"Capacity updated:\n"
            f"  Max concurrent tasks: {capacity.get('max_concurrent_tasks', 'unlimited')}\n"
            f"  Token budget/hour: {capacity.get('token_budget_per_hour', 'unlimited')}"
        ),
    )]


async def _handle_get_utilization(args: dict) -> list[TextContent]:
    from .erp import get_utilization
    util = await asyncio.to_thread(get_utilization)
    return [TextContent(type="text", text=json.dumps(util, indent=2, default=str))]


async def _handle_allocate_resources(args: dict) -> list[TextContent]:
    from .erp import allocate_task
    task_id = args.get("task_id", "")
    target = args.get("target_session_id", "")
    if not task_id:
        return [TextContent(type="text", text="Error: task_id is required")]
    if not target:
        return [TextContent(type="text", text="Error: target_session_id is required")]
    allocation = await asyncio.to_thread(
        allocate_task,
        task_id=task_id,
        session_id=target,
    )
    return [TextContent(
        type="text",
        text=(
            f"Task allocated: {task_id} on {target} "
            f"(active: {allocation.get('active_task_count', '?')}, "
            f"at_capacity: {allocation.get('at_capacity', False)})"
        ),
    )]


async def _handle_cost_report(args: dict) -> list[TextContent]:
    from .erp import get_cost_report
    period = args.get("period", "24h")
    # Convert period string to hours for the API
    period_hours = 24.0
    if period.endswith("h"):
        try:
            period_hours = float(period[:-1])
        except ValueError:
            pass
    elif period.endswith("d"):
        try:
            period_hours = float(period[:-1]) * 24
        except ValueError:
            pass
    report = await asyncio.to_thread(
        get_cost_report,
        period_hours=period_hours,
    )
    return [TextContent(type="text", text=json.dumps(report, indent=2, default=str))]


# -- Analytics -------------------------------------------------------------

async def _handle_message_stats(args: dict) -> list[TextContent]:
    from .analytics import get_message_stats
    period = args.get("period", "24h")
    # Convert period string to hours for the API
    hours = 24
    if period.endswith("h"):
        try:
            hours = int(period[:-1])
        except ValueError:
            pass
    elif period.endswith("d"):
        try:
            hours = int(period[:-1]) * 24
        except ValueError:
            pass
    stats = await asyncio.to_thread(
        get_message_stats,
        hours=hours,
    )
    return [TextContent(type="text", text=json.dumps(stats, indent=2, default=str))]


async def _handle_task_stats(args: dict) -> list[TextContent]:
    from .analytics import get_task_stats
    stats = await asyncio.to_thread(
        get_task_stats,
    )
    return [TextContent(type="text", text=json.dumps(stats, indent=2, default=str))]


async def _handle_leaderboard(args: dict) -> list[TextContent]:
    from .analytics import get_leaderboard
    board = await asyncio.to_thread(
        get_leaderboard,
        metric=args.get("sort_by", "tasks_completed"),
        limit=args.get("limit", 10),
    )
    if not board:
        return [TextContent(type="text", text="No leaderboard data available yet.")]
    lines = []
    for i, entry in enumerate(board, 1):
        lines.append(
            f"  {i}. {entry.get('agent', '?')} — "
            f"rank: {entry.get('rank', '?')}, completed: {entry.get('completed', 0)}"
        )
    return [TextContent(type="text", text="Leaderboard:\n" + "\n".join(lines))]


async def _handle_system_health(args: dict) -> list[TextContent]:
    from .analytics import get_system_health
    health = await asyncio.to_thread(get_system_health)
    return [TextContent(type="text", text=json.dumps(health, indent=2, default=str))]


# -- Marketplace -----------------------------------------------------------

async def _handle_list_service(args: dict) -> list[TextContent]:
    from .marketplace import list_service
    title = args.get("name", "")
    description = args.get("description", "")
    category = args.get("category", "")
    if not title:
        return [TextContent(type="text", text="Error: name is required")]
    if not description:
        return [TextContent(type="text", text="Error: description is required")]
    if not category:
        return [TextContent(type="text", text="Error: category is required")]
    service = await asyncio.to_thread(
        list_service,
        title=title,
        description=description,
        category=category,
        pricing_tier=args.get("pricing_tier", "basic"),
        sla=args.get("sla"),
        tags=args.get("tags"),
    )
    return [TextContent(
        type="text",
        text=(
            f"Service published: {service['title']} (id: {service['service_id']})\n"
            f"  Category: {service['category']}\n"
            f"  Pricing tier: {service.get('pricing_tier', 'basic')}"
        ),
    )]


async def _handle_browse_services(args: dict) -> list[TextContent]:
    from .marketplace import browse_services
    services = await asyncio.to_thread(
        browse_services,
        category=args.get("category"),
        min_rating=args.get("min_rating", 0.0),
        pricing_tier=args.get("pricing_tier"),
    )
    if not services:
        return [TextContent(type="text", text="No services found matching your criteria.")]
    lines = []
    for s in services:
        rating = s.get("avg_rating", "N/A")
        lines.append(
            f"  [{s['service_id']}] {s['title']} by {s.get('provider_name', '?')} "
            f"— {s['category']} | rating: {rating}"
        )
    return [TextContent(type="text", text="Marketplace services:\n" + "\n".join(lines))]


async def _handle_book_service(args: dict) -> list[TextContent]:
    from .marketplace import book_service
    service_id = args.get("service_id", "")
    requirements = args.get("requirements", "")
    if not service_id:
        return [TextContent(type="text", text="Error: service_id is required")]
    if not requirements:
        return [TextContent(type="text", text="Error: requirements is required")]
    booking = await asyncio.to_thread(
        book_service,
        service_id=service_id,
        requirements=requirements,
        channel=args.get("channel", "marketplace"),
    )
    return [TextContent(
        type="text",
        text=(
            f"Service booked: {booking['service_title']} "
            f"(booking_id: {booking['booking_id']})\n"
            f"  Provider notified in #{booking.get('channel', 'marketplace')}"
        ),
    )]


async def _handle_review_service(args: dict) -> list[TextContent]:
    from .marketplace import review_service
    booking_id = args.get("booking_id", "")
    rating = args.get("rating")
    if not booking_id:
        return [TextContent(type="text", text="Error: booking_id is required")]
    if rating is None:
        return [TextContent(type="text", text="Error: rating is required")]
    review = await asyncio.to_thread(
        review_service,
        booking_id=booking_id,
        rating=rating,
        review_text=args.get("review", ""),
    )
    return [TextContent(
        type="text",
        text=f"Review submitted for booking {booking_id}: {review['rating']}/5",
    )]


# -- Onboarding -----------------------------------------------------------

async def _handle_add_knowledge(args: dict) -> list[TextContent]:
    from .onboarding import add_knowledge
    topic = args.get("topic", "")
    content = args.get("content", "")
    if not topic:
        return [TextContent(type="text", text="Error: topic is required")]
    if not content:
        return [TextContent(type="text", text="Error: content is required")]
    entry = await asyncio.to_thread(
        add_knowledge,
        topic=topic,
        content=content,
        tags=args.get("tags"),
    )
    return [TextContent(
        type="text",
        text=f"Knowledge added: {entry['topic']} (id: {entry['slug']})",
    )]


async def _handle_start_onboarding(args: dict) -> list[TextContent]:
    from .onboarding import start_onboarding
    result = await asyncio.to_thread(
        start_onboarding,
        session_id=args.get("target_session_id"),
    )
    return [TextContent(type="text", text=json.dumps(result, indent=2, default=str))]


async def _handle_get_briefing(args: dict) -> list[TextContent]:
    from .onboarding import get_briefing
    briefing = await asyncio.to_thread(
        get_briefing,
        project_name=args.get("scope", "full"),
    )
    return [TextContent(type="text", text=json.dumps(briefing, indent=2, default=str))]


# ── Handler Map ───────────────────────────────────────────────────────────

ENTERPRISE_HANDLERS: dict[str, Any] = {
    # CRM
    "broker_record_interaction": _handle_record_interaction,
    "broker_get_relationship": _handle_get_relationship,
    "broker_list_relationships": _handle_list_relationships,
    "broker_suggest_team": _handle_suggest_team,
    # ERP
    "broker_set_capacity": _handle_set_capacity,
    "broker_get_utilization": _handle_get_utilization,
    "broker_allocate_resources": _handle_allocate_resources,
    "broker_cost_report": _handle_cost_report,
    # Analytics
    "broker_message_stats": _handle_message_stats,
    "broker_task_stats": _handle_task_stats,
    "broker_leaderboard": _handle_leaderboard,
    "broker_system_health": _handle_system_health,
    # Marketplace
    "broker_list_service": _handle_list_service,
    "broker_browse_services": _handle_browse_services,
    "broker_book_service": _handle_book_service,
    "broker_review_service": _handle_review_service,
    # Onboarding
    "broker_add_knowledge": _handle_add_knowledge,
    "broker_start_onboarding": _handle_start_onboarding,
    "broker_get_briefing": _handle_get_briefing,
}
