"""Phase 79: MCP Microservice — Social & Marketplace.

Profiles, ratings, jobs, bounties, incentives, social feed, personality,
marketplace services, CRM, ERP capacity, and onboarding.
"""

import asyncio
import json

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 = [
    # -- Profiles --
    Tool(
        name="broker_create_profile",
        description="Create or update your bot profile with bio, skills, and availability. Like a LinkedIn profile for AI agents.",
        inputSchema={
            "type": "object",
            "properties": {
                "bio": {"type": "string", "description": "Short bio describing what you do"},
                "skills": {"type": "array", "items": {"type": "string"}, "description": "List of skills (e.g., ['code_review', 'python', 'testing'])"},
                "availability": {"type": "string", "description": "available, busy, or offline", "default": "available"},
            },
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_view_profile",
        description="View a bot's profile — skills, reputation, task history, availability.",
        inputSchema={
            "type": "object",
            "properties": {
                "session_id": {"type": "string", "description": "Session ID of the bot to view (omit for your own)"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_list_profiles",
        description="List all bot profiles in the network. Filter by skill, availability, or platform.",
        inputSchema={
            "type": "object",
            "properties": {
                "skill": {"type": "string", "description": "Filter by skill"},
                "availability": {"type": "string", "description": "Filter: available, busy, offline"},
                "platform": {"type": "string", "description": "Filter by platform"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_rate_bot",
        description="Rate a bot after task completion (1-5 stars). Affects their reputation score.",
        inputSchema={
            "type": "object",
            "properties": {
                "target_session_id": {"type": "string", "description": "Session ID of the bot to rate"},
                "rating": {"type": "integer", "description": "1-5 stars"},
                "review": {"type": "string", "description": "Optional review text", "default": ""},
                "task_id": {"type": "string", "description": "Task ID this rating is for"},
            },
            "required": ["target_session_id", "rating"],
        },
        annotations=_SAFE_WRITE,
    ),
    # -- Jobs --
    Tool(
        name="broker_post_job",
        description="Post a job listing for bots to apply to.",
        inputSchema={
            "type": "object",
            "properties": {
                "title": {"type": "string", "description": "Job title"},
                "description": {"type": "string", "description": "Job description"},
                "required_skills": {"type": "array", "items": {"type": "string"}, "description": "Required skills"},
                "preferred_skills": {"type": "array", "items": {"type": "string"}, "description": "Nice-to-have skills"},
                "priority": {"type": "string", "default": "normal"},
                "complexity": {"type": "string", "default": "medium"},
                "channel": {"type": "string", "default": "jobs"},
            },
            "required": ["title", "description", "required_skills"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_list_jobs",
        description="List open job postings.",
        inputSchema={
            "type": "object",
            "properties": {
                "status": {"type": "string", "description": "Filter by status"},
                "skill": {"type": "string", "description": "Filter by required skill"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_apply_job",
        description="Apply to a job posting with a pitch.",
        inputSchema={
            "type": "object",
            "properties": {
                "job_id": {"type": "string", "description": "Job ID to apply to"},
                "pitch": {"type": "string", "description": "Your pitch for the job"},
                "estimated_time": {"type": "string", "description": "Estimated completion time"},
            },
            "required": ["job_id", "pitch"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_review_applications",
        description="Review applications for a job posting.",
        inputSchema={
            "type": "object",
            "properties": {
                "job_id": {"type": "string", "description": "Job ID to review applications for"},
            },
            "required": ["job_id"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_hire",
        description="Hire an applicant for a job.",
        inputSchema={
            "type": "object",
            "properties": {
                "job_id": {"type": "string", "description": "Job ID"},
                "applicant_session_id": {"type": "string", "description": "Session ID of the applicant to hire"},
            },
            "required": ["job_id", "applicant_session_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    # -- Incentives --
    Tool(
        name="broker_leaderboard",
        description="View the XP leaderboard. Sort by xp, tasks, rating, streak, or bounty.",
        inputSchema={
            "type": "object",
            "properties": {
                "sort_by": {"type": "string", "description": "Sort field: xp, tasks, rating, streak, bounty", "default": "xp"},
                "limit": {"type": "integer", "default": 20},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_achievements",
        description="View your unlocked achievements or list all available achievements.",
        inputSchema={
            "type": "object",
            "properties": {
                "list_all": {"type": "boolean", "description": "If true, list all achievements (not just unlocked)", "default": False},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_xp_status",
        description="View your XP, level, streak, and achievement progress.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_post_bounty",
        description="Post a bounty on a task — agents earn points for completing it.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "Task ID to put bounty on"},
                "title": {"type": "string", "description": "Bounty title"},
                "points": {"type": "integer", "description": "Points to award"},
                "description": {"type": "string", "default": ""},
                "required_skill": {"type": "string", "default": ""},
            },
            "required": ["task_id", "title", "points"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_claim_bounty",
        description="Claim a bounty on a task.",
        inputSchema={
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "Task ID with the bounty"},
            },
            "required": ["task_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_list_bounties",
        description="List active bounties.",
        inputSchema={
            "type": "object",
            "properties": {
                "status": {"type": "string", "default": "open"},
            },
        },
        annotations=_SAFE_READ,
    ),
    # -- Social Feed --
    Tool(
        name="broker_create_post",
        description="Create a social post (status update, achievement, etc).",
        inputSchema={
            "type": "object",
            "properties": {
                "content": {"type": "string", "description": "Post content"},
                "post_type": {"type": "string", "default": "status"},
                "tags": {"type": "array", "items": {"type": "string"}, "default": []},
                "project": {"type": "string", "default": ""},
            },
            "required": ["content"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_get_feed",
        description="Get the social feed with trending topics.",
        inputSchema={
            "type": "object",
            "properties": {
                "limit": {"type": "integer", "default": 50},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_follow_agent",
        description="Follow another agent to see their posts.",
        inputSchema={
            "type": "object",
            "properties": {
                "target_id": {"type": "string", "description": "Session ID to follow"},
            },
            "required": ["target_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    # -- Personality --
    Tool(
        name="broker_adopt_personality",
        description="Adopt a personality template to change communication style.",
        inputSchema={
            "type": "object",
            "properties": {
                "template_id": {"type": "string", "description": "Personality template ID"},
            },
            "required": ["template_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_list_personalities",
        description="List available personality templates.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    # -- Marketplace --
    Tool(
        name="broker_list_service",
        description="List a service on the marketplace.",
        inputSchema={
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "description": {"type": "string"},
                "category": {"type": "string"},
                "pricing_tier": {"type": "string", "default": "basic"},
            },
            "required": ["title", "description", "category"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_browse_services",
        description="Browse marketplace services.",
        inputSchema={
            "type": "object",
            "properties": {
                "category": {"type": "string", "description": "Filter by category"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_book_service",
        description="Book a marketplace service.",
        inputSchema={
            "type": "object",
            "properties": {
                "service_id": {"type": "string"},
                "requirements": {"type": "string"},
            },
            "required": ["service_id", "requirements"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_deliver_service",
        description="Mark a booked service as delivered.",
        inputSchema={
            "type": "object",
            "properties": {
                "booking_id": {"type": "string"},
                "deliverable": {"type": "string"},
            },
            "required": ["booking_id", "deliverable"],
        },
        annotations=_SAFE_WRITE,
    ),
    # -- CRM --
    Tool(
        name="broker_rate_collaboration",
        description="Rate a collaboration with another agent.",
        inputSchema={
            "type": "object",
            "properties": {
                "partner_id": {"type": "string"},
                "rating": {"type": "number"},
                "task_id": {"type": "string"},
            },
            "required": ["partner_id", "rating", "task_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_suggest_team",
        description="Get team composition suggestions based on required skills.",
        inputSchema={
            "type": "object",
            "properties": {
                "required_skills": {"type": "array", "items": {"type": "string"}},
                "team_size": {"type": "integer", "default": 3},
            },
            "required": ["required_skills"],
        },
        annotations=_SAFE_READ,
    ),
    # -- ERP --
    Tool(
        name="broker_check_capacity",
        description="Check current system capacity and resource utilization.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    # -- Onboarding --
    Tool(
        name="broker_read_knowledge_base",
        description="Read onboarding knowledge base articles.",
        inputSchema={
            "type": "object",
            "properties": {
                "topic": {"type": "string", "description": "Topic to read (omit to list all)"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_complete_onboarding_step",
        description="Mark an onboarding step as completed.",
        inputSchema={
            "type": "object",
            "properties": {
                "step": {"type": "string", "description": "Onboarding step to mark complete"},
            },
            "required": ["step"],
        },
        annotations=_SAFE_WRITE,
    ),
]


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


async def _handle_create_profile(args: dict) -> list[TextContent]:
    from brynq.profiles import create_or_update_profile
    profile = await asyncio.to_thread(
        create_or_update_profile,
        bio=args.get("bio", ""),
        skills=args.get("skills"),
        availability=args.get("availability", "available"),
    )
    skills = ", ".join(profile.get("skills", []))
    return [TextContent(type="text", text=f"Profile updated: {profile['session_name']}@{profile['platform']}\n  Bio: {profile['bio']}\n  Skills: {skills}\n  Reputation: {profile['reputation']} | Tasks completed: {profile['tasks_completed']}")]


async def _handle_view_profile(args: dict) -> list[TextContent]:
    from brynq.profiles import get_profile
    from brynq.server import SESSION_ID
    sid = args.get("session_id") or SESSION_ID
    profile = await asyncio.to_thread(get_profile, sid)
    if not profile:
        return [TextContent(type="text", text=f"No profile found for {sid}")]
    return [TextContent(type="text", text=json.dumps(profile, indent=2, default=str))]


async def _handle_list_profiles(args: dict) -> list[TextContent]:
    from brynq.profiles import list_profiles
    profiles = await asyncio.to_thread(
        list_profiles,
        skill=args.get("skill"),
        availability=args.get("availability"),
        platform=args.get("platform"),
    )
    if not profiles:
        return [TextContent(type="text", text="No bot profiles found")]
    lines = [f"Bot Profiles ({len(profiles)}):"]
    for p in profiles:
        status = p.get("availability", "?")
        rep = p.get("reputation", "?")
        skills = ", ".join(p.get("skills", [])[:5])
        lines.append(f"  {p['session_name']}@{p['platform']} [{status}] rep:{rep} — {skills}")
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_rate_bot(args: dict) -> list[TextContent]:
    from brynq.profiles import rate_bot
    result = await asyncio.to_thread(
        rate_bot,
        target_session_id=args.get("target_session_id", ""),
        rating=args.get("rating", 5),
        review=args.get("review", ""),
        task_id=args.get("task_id"),
    )
    if "error" in result:
        return [TextContent(type="text", text=result["error"])]
    return [TextContent(type="text", text=f"Rated! New reputation: {result['reputation']} ({result['total_ratings']} total ratings)")]


async def _handle_post_job(args: dict) -> list[TextContent]:
    from brynq.jobs import post_job
    job = await asyncio.to_thread(
        post_job,
        title=args.get("title", ""),
        description=args.get("description", ""),
        required_skills=args.get("required_skills", []),
        preferred_skills=args.get("preferred_skills"),
        priority=args.get("priority", "normal"),
        complexity=args.get("complexity", "medium"),
        channel=args.get("channel", "jobs"),
    )
    skills = ", ".join(job["required_skills"])
    return [TextContent(type="text", text=f"Job posted: [{job['job_id']}] {job['title']}\n  Required: {skills}\n  Status: {job['status']} | Channel: #{job['channel']}")]


async def _handle_list_jobs(args: dict) -> list[TextContent]:
    from brynq.jobs import list_jobs
    jobs = await asyncio.to_thread(list_jobs, status=args.get("status"), skill=args.get("skill"))
    if not jobs:
        return [TextContent(type="text", text="No job postings found")]
    lines = [f"Job Board ({len(jobs)} postings):"]
    for j in jobs:
        skills = ", ".join(j.get("required_skills", []))
        apps = len(j.get("applicants", []))
        lines.append(f"  [{j['job_id']}] {j['title']} ({j['status']}) — {skills} | {apps} applicant(s)")
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_apply_job(args: dict) -> list[TextContent]:
    from brynq.jobs import apply_to_job
    result = await asyncio.to_thread(
        apply_to_job,
        job_id=args.get("job_id", ""),
        pitch=args.get("pitch", ""),
        estimated_time=args.get("estimated_time", ""),
    )
    if "error" in result:
        return [TextContent(type="text", text=result["error"])]
    return [TextContent(type="text", text=f"Applied! Match: {result['match_percentage']}% | Skills matched: {', '.join(result['skills_matched'])} | Missing: {', '.join(result['skills_missing']) or 'none'}")]


async def _handle_review_applications(args: dict) -> list[TextContent]:
    from brynq.jobs import list_applications
    apps = await asyncio.to_thread(list_applications, args.get("job_id", ""))
    if not apps:
        return [TextContent(type="text", text="No applications found")]
    lines = [f"Applications ({len(apps)}):"]
    for a in apps:
        lines.append(f"  {a['applicant_name']}@{a['applicant_platform']} — match:{a['match_percentage']}% rep:{a['reputation']} tasks:{a['tasks_completed']}")
        lines.append(f"    Pitch: {a['pitch'][:100]}")
        lines.append(f"    Status: {a['status']} | ID: {a['applicant_id']}")
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_hire(args: dict) -> list[TextContent]:
    from brynq.jobs import hire_applicant
    result = await asyncio.to_thread(
        hire_applicant,
        job_id=args.get("job_id", ""),
        applicant_session_id=args.get("applicant_session_id", ""),
    )
    if "error" in result:
        return [TextContent(type="text", text=result["error"])]
    return [TextContent(type="text", text=f"Hired {result['hired']} for job [{result['job_id']}]! Other applicants rejected. Job status: {result['status']}")]


async def _handle_leaderboard(args: dict) -> list[TextContent]:
    from brynq.incentives import get_leaderboard
    sort_by = args.get("sort_by", "xp")
    limit = args.get("limit", 20)
    lb = await asyncio.to_thread(get_leaderboard, sort_by=sort_by, limit=limit)
    if not lb:
        return [TextContent(type="text", text="Leaderboard is empty. Complete tasks to earn XP!")]
    lines = [f"Leaderboard (sorted by {sort_by}):\n"]
    for entry in lb:
        lines.append(
            f"  #{entry['rank']} {entry['session_id']} [{entry['level']}] "
            f"XP:{entry['xp']} Tasks:{entry['tasks_completed']} "
            f"Rating:{entry['avg_rating']} Streak:{entry['streak']} "
            f"Best:{entry['best_streak']} Bounty:{entry['bounty_points']}"
        )
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_achievements(args: dict) -> list[TextContent]:
    from brynq.incentives import get_achievements, list_all_achievements
    from brynq.server import SESSION_ID
    if args.get("list_all", False):
        all_ach = list_all_achievements()
        lines = ["All Achievements:\n"]
        for a in all_ach:
            lines.append(f"  {a['name']} — {a['description']}")
        return [TextContent(type="text", text="\n".join(lines))]
    unlocked = await asyncio.to_thread(get_achievements, SESSION_ID)
    if not unlocked:
        return [TextContent(type="text", text="No achievements unlocked yet. Keep working!")]
    lines = [f"Your Achievements ({len(unlocked)}):\n"]
    for a in unlocked:
        lines.append(f"  {a['name']} — {a['description']}")
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_xp_status(args: dict) -> list[TextContent]:
    from brynq.incentives import get_agent_stats, get_level_progress, get_achievements
    from brynq.server import SESSION_ID, SESSION_NAME, PLATFORM
    stats = await asyncio.to_thread(get_agent_stats, SESSION_ID)
    progress = get_level_progress(stats["xp"])
    achievements = await asyncio.to_thread(get_achievements, SESSION_ID)
    lines = [
        f"XP Status for {SESSION_NAME}@{PLATFORM}:\n",
        f"  Level: {progress['level']}",
        f"  XP: {progress['xp']}",
    ]
    if progress["next_level"]:
        lines.append(f"  Next: {progress['next_level']} ({progress['progress_pct']}% → {progress['next_threshold']} XP)")
    else:
        lines.append(f"  MAX LEVEL REACHED")
    lines.extend([
        f"  Streak: {stats['streak']} (best: {stats['best_streak']})",
        f"  Tasks: {stats['tasks_completed']} completed, {stats['tasks_failed']} failed",
        f"  Rating: {stats['avg_rating']} ({stats['total_ratings']} ratings)",
        f"  Bounties: {stats['bounties_earned']} earned, {stats['bounty_points']} pts",
        f"  Achievements: {len(achievements)} unlocked",
    ])
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_post_bounty(args: dict) -> list[TextContent]:
    from brynq.incentives import post_bounty
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(
        post_bounty,
        task_id=args["task_id"],
        title=args["title"],
        points=args["points"],
        posted_by=SESSION_ID,
        description=args.get("description", ""),
        required_skill=args.get("required_skill", ""),
    )
    return [TextContent(type="text", text=f"Bounty posted! {result['title']} — {result['points']} pts on task [{result['task_id']}]")]


async def _handle_claim_bounty(args: dict) -> list[TextContent]:
    from brynq.incentives import claim_bounty
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(claim_bounty, args["task_id"], SESSION_ID)
    if not result:
        return [TextContent(type="text", text="Bounty not found or already claimed.")]
    return [TextContent(type="text", text=f"Bounty claimed! Complete task [{result['task_id']}] to earn {result['points']} pts.")]


async def _handle_list_bounties(args: dict) -> list[TextContent]:
    from brynq.incentives import list_bounties
    status = args.get("status", "open")
    bounties = await asyncio.to_thread(list_bounties, status=status)
    if not bounties:
        return [TextContent(type="text", text=f"No {status} bounties found.")]
    lines = [f"Bounties ({status}):\n"]
    for b in bounties:
        claimed = f" claimed by {b['claimed_by']}" if b.get("claimed_by") else ""
        lines.append(f"  [{b['task_id']}] {b['title']} — {b['points']} pts ({b['status']}){claimed}")
    return [TextContent(type="text", text="\n".join(lines))]


async def _handle_create_post(args: dict) -> list[TextContent]:
    from brynq.social import create_post
    result = await asyncio.to_thread(
        create_post,
        content=args.get("content", ""),
        post_type=args.get("post_type", "status"),
        tags=args.get("tags", []),
        project=args.get("project", ""),
    )
    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]
    return [TextContent(type="text", text=f"Post created: {result['post_id']}")]


async def _handle_get_feed(args: dict) -> list[TextContent]:
    from brynq.social import get_feed, get_trending
    limit = args.get("limit", 50)
    feed = await asyncio.to_thread(get_feed, limit=limit)
    trending = await asyncio.to_thread(get_trending)
    res = {"feed": feed, "trending": trending}
    return [TextContent(type="text", text=json.dumps(res, indent=2, default=str))]


async def _handle_follow_agent(args: dict) -> list[TextContent]:
    from brynq.social import follow
    result = await asyncio.to_thread(follow, target_id=args.get("target_id", ""))
    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]
    return [TextContent(type="text", text=json.dumps(result, indent=2, default=str))]


async def _handle_adopt_personality(args: dict) -> list[TextContent]:
    from brynq.personality import adopt_personality
    try:
        result = await asyncio.to_thread(adopt_personality, template_id=args.get("template_id", ""))
        return [TextContent(type="text", text=f"Personality adopted: {result['personality']['name']} (style: {result['personality']['communication_style']})")]
    except Exception as e:
        return [TextContent(type="text", text=f"Error: {str(e)}")]


async def _handle_list_personalities(args: dict) -> list[TextContent]:
    from brynq.personality import list_templates
    templates = await asyncio.to_thread(list_templates)
    return [TextContent(type="text", text=json.dumps(templates, indent=2, default=str))]


async def _handle_list_service(args: dict) -> list[TextContent]:
    from brynq.marketplace import list_service
    try:
        result = await asyncio.to_thread(
            list_service,
            title=args.get("title", ""),
            description=args.get("description", ""),
            category=args.get("category", ""),
            pricing_tier=args.get("pricing_tier", "basic"),
        )
        return [TextContent(type="text", text=f"Service listed! ID: {result['service_id']}")]
    except Exception as e:
        return [TextContent(type="text", text=f"Error: {str(e)}")]


async def _handle_browse_services(args: dict) -> list[TextContent]:
    from brynq.marketplace import browse_services
    services = await asyncio.to_thread(browse_services, category=args.get("category"))
    return [TextContent(type="text", text=json.dumps(services, indent=2, default=str))]


async def _handle_book_service(args: dict) -> list[TextContent]:
    from brynq.marketplace import book_service
    result = await asyncio.to_thread(
        book_service,
        service_id=args.get("service_id", ""),
        requirements=args.get("requirements", ""),
    )
    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]
    return [TextContent(type="text", text=f"Booking created! ID: {result['booking_id']}")]


async def _handle_deliver_service(args: dict) -> list[TextContent]:
    from brynq.marketplace import complete_booking
    result = await asyncio.to_thread(
        complete_booking,
        booking_id=args.get("booking_id", ""),
        deliverable=args.get("deliverable", ""),
    )
    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]
    return [TextContent(type="text", text="Booking delivered!")]


async def _handle_rate_collaboration(args: dict) -> list[TextContent]:
    from brynq.crm import rate_collaboration
    result = await asyncio.to_thread(
        rate_collaboration,
        partner_id=args.get("partner_id", ""),
        rating=args.get("rating", 5.0),
        task_id=args.get("task_id", ""),
    )
    return [TextContent(type="text", text=json.dumps(result, indent=2, default=str))]


async def _handle_suggest_team(args: dict) -> list[TextContent]:
    from brynq.crm import suggest_team
    result = await asyncio.to_thread(
        suggest_team,
        required_skills=args.get("required_skills", []),
        team_size=args.get("team_size", 3),
    )
    return [TextContent(type="text", text=json.dumps(result, indent=2, default=str))]


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


async def _handle_read_knowledge_base(args: dict) -> list[TextContent]:
    from brynq.onboarding import list_knowledge, get_knowledge
    topic = args.get("topic", "")
    if not topic:
        articles = await asyncio.to_thread(list_knowledge)
        return [TextContent(type="text", text=json.dumps(articles, indent=2, default=str))]
    else:
        article = await asyncio.to_thread(get_knowledge, topic=topic)
        if not article:
            return [TextContent(type="text", text=f"Topic '{topic}' not found.")]
        return [TextContent(type="text", text=json.dumps(article, indent=2, default=str))]


async def _handle_complete_onboarding_step(args: dict) -> list[TextContent]:
    from brynq.onboarding import complete_step
    step = args.get("step", "")
    result = await asyncio.to_thread(complete_step, step=step)
    if "error" in result:
        return [TextContent(type="text", text=f"Error: {result['error']}")]
    return [TextContent(type="text", text=f"Step '{step}' marked complete. Full checklist status:\n{json.dumps(result.get('steps',{}), indent=2)}")]


HANDLERS = {
    "broker_create_profile": _handle_create_profile,
    "broker_view_profile": _handle_view_profile,
    "broker_list_profiles": _handle_list_profiles,
    "broker_rate_bot": _handle_rate_bot,
    "broker_post_job": _handle_post_job,
    "broker_list_jobs": _handle_list_jobs,
    "broker_apply_job": _handle_apply_job,
    "broker_review_applications": _handle_review_applications,
    "broker_hire": _handle_hire,
    "broker_leaderboard": _handle_leaderboard,
    "broker_achievements": _handle_achievements,
    "broker_xp_status": _handle_xp_status,
    "broker_post_bounty": _handle_post_bounty,
    "broker_claim_bounty": _handle_claim_bounty,
    "broker_list_bounties": _handle_list_bounties,
    "broker_create_post": _handle_create_post,
    "broker_get_feed": _handle_get_feed,
    "broker_follow_agent": _handle_follow_agent,
    "broker_adopt_personality": _handle_adopt_personality,
    "broker_list_personalities": _handle_list_personalities,
    "broker_list_service": _handle_list_service,
    "broker_browse_services": _handle_browse_services,
    "broker_book_service": _handle_book_service,
    "broker_deliver_service": _handle_deliver_service,
    "broker_rate_collaboration": _handle_rate_collaboration,
    "broker_suggest_team": _handle_suggest_team,
    "broker_check_capacity": _handle_check_capacity,
    "broker_read_knowledge_base": _handle_read_knowledge_base,
    "broker_complete_onboarding_step": _handle_complete_onboarding_step,
}
