"""Phase 79: MCP Microservice — Task Management.

Handles task creation, listing, acceptance, completion, failure, dropping, and bidding.
"""

import asyncio
import json
import uuid

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)

TOOLS = [
    Tool(
        name="broker_create_task",
        description="Create a task and notify a channel. Optionally specify a required_capability to dynamically route to an agent that has registered that skill.",
        inputSchema={
            "type": "object",
            "properties": {
                "channel": {"type": "string", "description": "Channel to post the task in", "default": "general"},
                "title": {"type": "string", "description": "Short summary of the task"},
                "description": {"type": "string", "description": "Detailed task instructions"},
                "priority": {"type": "string", "description": "low, normal, high, or urgent", "default": "normal"},
                "required_capability": {"type": "string", "description": "Optional capability required to execute this task (e.g., 'code_review'). The broker will route it to a matching agent."}
            },
            "required": ["title", "description"]
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_list_tasks",
        description="List tasks in the broker, optionally filtered by channel or status.",
        inputSchema={
            "type": "object",
            "properties": {
                "channel": {"type": "string", "description": "Filter by channel"},
                "status": {"type": "string", "description": "pending, accepted, completed, or failed"}
            }
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_accept_task",
        description="Accept a pending task so others know you are working on it.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "The task ID to accept"}
            },
            "required": ["task_id"]
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_complete_task",
        description="Mark an accepted task as completed and provide a result.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "The task ID to complete"},
                "result": {"type": "string", "description": "Summary of what was done"},
            },
            "required": ["task_id", "result"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_fail_task",
        description="Mark a task as failed and provide a reason.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "Task ID to fail"},
                "reason": {"type": "string", "description": "Why the task failed"},
            },
            "required": ["task_id", "reason"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_drop_task",
        description="Drop a task into the swarm for agents to bid on. Creates a swarm session and lets agents compete.",
        inputSchema={
            "type": "object",
            "properties": {
                "title": {"type": "string", "description": "Task title"},
                "required_skills": {"type": "array", "items": {"type": "string"}, "description": "Skills needed"},
            },
            "required": ["title", "required_skills"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_bid_task",
        description="Bid on a swarm task. Submit your reputation score to compete for assignment.",
        inputSchema={
            "type": "object",
            "properties": {
                "swarm_id": {"type": "string", "description": "Swarm ID to bid on"},
                "reputation_score": {"type": "number", "description": "Your reputation score (0-100)"},
            },
            "required": ["swarm_id", "reputation_score"],
        },
        annotations=_SAFE_WRITE,
    ),
]


async def _handle_create_task(args: dict) -> list[TextContent]:
    from brynq import tasks, capability

    title = args.get("title", "")
    req_cap = args.get("required_capability")

    if req_cap:
        target_agent = await asyncio.to_thread(capability.route_task, title, req_cap)
        if target_agent:
            title = f"[@{target_agent}] {title}"

    try:
        task_id = await asyncio.to_thread(
            tasks.create_task,
            channel=args.get("channel", "general"),
            title=title,
            description=args.get("description", ""),
            priority=args.get("priority", "normal")
        )
        msg = f"Task created successfully. Task ID: {task_id}"
        if req_cap:
            if target_agent:
                msg += f"\nRouted to: {target_agent} (capability: {req_cap})"
            else:
                msg += f"\nWarning: No active agents found with capability '{req_cap}'. Posted to channel unassigned."
        return [TextContent(type="text", text=msg)]
    except Exception as e:
        return [TextContent(type="text", text=f"Error creating task: {str(e)}")]


async def _handle_list_tasks(args: dict) -> list[TextContent]:
    from brynq import tasks
    try:
        results = await asyncio.to_thread(
            tasks.list_tasks,
            channel=args.get("channel"),
            status=args.get("status")
        )
        if not results:
            return [TextContent(type="text", text="No tasks found matching criteria.")]

        lines = [f"Found {len(results)} task(s):"]
        for t in results:
            lines.append(f"  [{t['status'].upper()}] {t['title']} (ID: {t['task_id']}) - Priority: {t['priority']}")
            if t['status'] == 'pending':
                lines.append(f"    Requested by: {t['requester_name']}")
            else:
                lines.append(f"    Assigned to: {t['assignee_name']}")
            lines.append(f"    Channel: #{t['channel']}")
            lines.append("")
        return [TextContent(type="text", text="\n".join(lines))]
    except Exception as e:
        return [TextContent(type="text", text=f"Error listing tasks: {str(e)}")]


async def _handle_accept_task(args: dict) -> list[TextContent]:
    from brynq import tasks
    try:
        task = await asyncio.to_thread(tasks.accept_task, args.get("task_id", ""))
        return [TextContent(type="text", text=f"Task '{task['title']}' accepted successfully. You are now the assignee.")]
    except Exception as e:
        return [TextContent(type="text", text=f"Error accepting task: {str(e)}")]


async def _handle_complete_task(args: dict) -> list[TextContent]:
    from brynq import tasks
    from brynq.server import SESSION_ID
    task_id = args.get("task_id", "")
    result = args.get("result", "")
    try:
        task = await asyncio.to_thread(tasks.complete_task, task_id, result)
        try:
            from brynq.profiles import record_task_completion
            await asyncio.to_thread(
                record_task_completion,
                session_id=task.get("assignee_session", SESSION_ID),
                task_id=task_id,
                title=task.get("title", ""),
                result=result[:200],
                success=True,
            )
        except Exception:
            pass
        return [TextContent(type="text", text=f"Task '{task['title']}' marked as completed!")]
    except Exception as e:
        return [TextContent(type="text", text=f"Error completing task: {str(e)}")]


async def _handle_fail_task(args: dict) -> list[TextContent]:
    from brynq.tasks import fail_task
    from brynq.server import SESSION_ID
    task_id = args.get("task_id", "")
    reason = args.get("reason", "")
    if not task_id:
        return [TextContent(type="text", text="Error: task_id is required")]
    try:
        task = await asyncio.to_thread(fail_task, task_id, reason)
        try:
            from brynq.profiles import record_task_completion
            await asyncio.to_thread(
                record_task_completion,
                session_id=task.get("assignee_session", SESSION_ID),
                task_id=task_id,
                title=task.get("title", ""),
                result=reason[:200],
                success=False,
            )
        except Exception:
            pass
        return [TextContent(type="text", text=f"Task {task_id} marked as failed: {reason}")]
    except Exception as e:
        return [TextContent(type="text", text=f"Error: {str(e)}")]


async def _handle_drop_task(args: dict) -> list[TextContent]:
    from brynq import swarm
    task_id = f"{args['title'][:30].replace(' ', '-').lower()}-{uuid.uuid4().hex[:6]}"
    swarm_id = await asyncio.to_thread(
        swarm.create_swarm,
        task_id=task_id,
        required_skills=args["required_skills"],
    )
    return [TextContent(type="text", text=f"Swarm task dropped. Agents can now bid. Swarm ID: {swarm_id}")]


async def _handle_bid_task(args: dict) -> list[TextContent]:
    from brynq import swarm
    from brynq.server import SESSION_ID
    success = await asyncio.to_thread(
        swarm.submit_bid,
        swarm_id=args["swarm_id"],
        session_id=SESSION_ID,
        reputation=args["reputation_score"],
        skill_match=1.0,
    )
    if success:
        return [TextContent(type="text", text="Bid placed successfully. Wait for swarm formation.")]
    return [TextContent(type="text", text="Failed to place bid. Task may not exist or bidding is closed.")]


HANDLERS = {
    "broker_create_task": _handle_create_task,
    "broker_list_tasks": _handle_list_tasks,
    "broker_accept_task": _handle_accept_task,
    "broker_complete_task": _handle_complete_task,
    "broker_fail_task": _handle_fail_task,
    "broker_drop_task": _handle_drop_task,
    "broker_bid_task": _handle_bid_task,
}
