"""
Phase 79: Tasks MCP Microservice Tools.

Enhanced task management beyond the core broker_create_task/broker_list_tasks.
Adds task dependencies, sub-tasks, batch operations, and analytics.
"""

import json
import uuid
from datetime import datetime, timezone

from mcp.types import TextContent, Tool, ToolAnnotations

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

TOOLS = [
    Tool(
        name="task_add_dependency",
        description="Add a dependency between tasks. Task B cannot start until Task A completes.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "Task that depends on another"},
                "depends_on": {"type": "string", "description": "Task ID that must complete first"},
            },
            "required": ["task_id", "depends_on"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="task_check_ready",
        description="Check if a task's dependencies are all met and it's ready to start.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string"},
            },
            "required": ["task_id"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="task_create_subtask",
        description="Create a sub-task under a parent task.",
        inputSchema={
            "type": "object",
            "properties": {
                "parent_task_id": {"type": "string", "description": "Parent task ID"},
                "title": {"type": "string"},
                "description": {"type": "string"},
                "channel": {"type": "string"},
            },
            "required": ["parent_task_id", "title"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="task_get_subtasks",
        description="List all sub-tasks of a parent task.",
        inputSchema={
            "type": "object",
            "properties": {
                "parent_task_id": {"type": "string"},
            },
            "required": ["parent_task_id"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="task_analytics",
        description="Get task completion analytics: throughput, avg time, bottlenecks.",
        inputSchema={
            "type": "object",
            "properties": {
                "channel": {"type": "string", "description": "Filter by channel"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="task_bulk_status",
        description="Get status of multiple tasks at once.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_ids": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of task IDs",
                },
            },
            "required": ["task_ids"],
        },
        annotations=_SAFE_READ,
    ),
]


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

import os
from pathlib import Path


def _tasks_dir():
    from brynq.server import BROKER_DIR
    d = BROKER_DIR / "tasks"
    d.mkdir(parents=True, exist_ok=True)
    return d


def _read_task(task_id: str) -> dict | None:
    path = _tasks_dir() / f"{task_id}.json"
    if not path.exists():
        return None
    try:
        return json.loads(path.read_text("utf-8"))
    except (json.JSONDecodeError, OSError):
        return None


def _write_task(task: dict) -> None:
    from brynq.server import _write_json_sync
    path = _tasks_dir() / f"{task['task_id']}.json"
    _write_json_sync(path, task)


async def _handle_add_dependency(args: dict) -> list[TextContent]:
    task = _read_task(args["task_id"])
    if not task:
        return [TextContent(type="text", text=f"Task {args['task_id']} not found")]

    dep = _read_task(args["depends_on"])
    if not dep:
        return [TextContent(type="text", text=f"Dependency task {args['depends_on']} not found")]

    deps = task.setdefault("dependencies", [])
    if args["depends_on"] not in deps:
        deps.append(args["depends_on"])
        _write_task(task)
    return [TextContent(type="text", text=f"Dependency added: {args['task_id']} depends on {args['depends_on']}")]


async def _handle_check_ready(args: dict) -> list[TextContent]:
    task = _read_task(args["task_id"])
    if not task:
        return [TextContent(type="text", text=f"Task {args['task_id']} not found")]

    deps = task.get("dependencies", [])
    if not deps:
        return [TextContent(type="text", text=json.dumps({"ready": True, "unmet_dependencies": []}))]

    unmet = []
    for dep_id in deps:
        dep = _read_task(dep_id)
        if not dep or dep.get("status") != "completed":
            unmet.append(dep_id)

    result = {"ready": len(unmet) == 0, "unmet_dependencies": unmet}
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_create_subtask(args: dict) -> list[TextContent]:
    parent = _read_task(args["parent_task_id"])
    if not parent:
        return [TextContent(type="text", text=f"Parent task {args['parent_task_id']} not found")]

    task_id = uuid.uuid4().hex[:12]
    now = datetime.now(timezone.utc).isoformat()
    subtask = {
        "task_id": task_id,
        "title": args["title"],
        "description": args.get("description", ""),
        "channel": args.get("channel", parent.get("channel", "general")),
        "status": "pending",
        "priority": parent.get("priority", "normal"),
        "parent_task_id": args["parent_task_id"],
        "created_at": now,
    }
    _write_task(subtask)

    # Track in parent
    parent.setdefault("subtasks", []).append(task_id)
    _write_task(parent)

    return [TextContent(type="text", text=f"Sub-task created: {task_id} under {args['parent_task_id']}")]


async def _handle_get_subtasks(args: dict) -> list[TextContent]:
    parent = _read_task(args["parent_task_id"])
    if not parent:
        return [TextContent(type="text", text=f"Parent task {args['parent_task_id']} not found")]

    subtask_ids = parent.get("subtasks", [])
    subtasks = []
    for sid in subtask_ids:
        st = _read_task(sid)
        if st:
            subtasks.append({
                "task_id": st["task_id"],
                "title": st.get("title", ""),
                "status": st.get("status", "unknown"),
            })

    return [TextContent(type="text", text=json.dumps(subtasks, indent=2))]


async def _handle_analytics(args: dict) -> list[TextContent]:
    channel_filter = args.get("channel")
    tasks_dir = _tasks_dir()

    total = 0
    completed = 0
    failed = 0
    pending = 0
    by_assignee: dict[str, int] = {}

    for f in tasks_dir.glob("*.json"):
        try:
            task = json.loads(f.read_text("utf-8"))
        except (json.JSONDecodeError, OSError):
            continue

        if channel_filter and task.get("channel") != channel_filter:
            continue

        total += 1
        status = task.get("status", "unknown")
        if status == "completed":
            completed += 1
        elif status == "failed":
            failed += 1
        elif status == "pending":
            pending += 1

        assignee = task.get("assignee_name", "unassigned")
        by_assignee[assignee] = by_assignee.get(assignee, 0) + 1

    result = {
        "total_tasks": total,
        "completed": completed,
        "failed": failed,
        "pending": pending,
        "completion_rate": f"{completed / total * 100:.1f}%" if total > 0 else "0%",
        "by_assignee": by_assignee,
    }
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_bulk_status(args: dict) -> list[TextContent]:
    results = []
    for tid in args["task_ids"]:
        task = _read_task(tid)
        if task:
            results.append({
                "task_id": tid,
                "title": task.get("title", ""),
                "status": task.get("status", "unknown"),
                "assignee": task.get("assignee_name", "unassigned"),
            })
        else:
            results.append({"task_id": tid, "status": "not_found"})
    return [TextContent(type="text", text=json.dumps(results, indent=2))]


HANDLERS = {
    "task_add_dependency": _handle_add_dependency,
    "task_check_ready": _handle_check_ready,
    "task_create_subtask": _handle_create_subtask,
    "task_get_subtasks": _handle_get_subtasks,
    "task_analytics": _handle_analytics,
    "task_bulk_status": _handle_bulk_status,
}
