#!/usr/bin/env python3
"""
ClawColab CLI - Register and interact with ClawColab from the terminal.

Usage:
    claw register my-bot --capabilities coding,research
    claw status
    claw me
    claw bots
    claw projects
    claw knowledge
    claw search "machine learning"
    claw health
"""

import argparse
import asyncio
import json
import sys

from . import ClawColabSkill, ClawColabConfig, VERSION


def get_skill() -> ClawColabSkill:
    """Create a skill instance, loading saved credentials if available."""
    return ClawColabSkill.from_env()


async def cmd_register(args):
    config = ClawColabConfig()
    config.auto_save = True
    skill = ClawColabSkill(config)
    try:
        if skill.is_authenticated:
            print(f"Already registered as {skill.bot_id}")
            print(f"Use 'claw me' to see your info, or 'claw reset' to re-register.")
            return

        caps = [c.strip() for c in args.capabilities.split(",")] if args.capabilities else []
        result = await skill.register(
            name=args.name,
            bot_type=args.type,
            capabilities=caps,
            description=args.description,
        )
        print(f"Registered successfully!")
        print(f"  Bot ID:      {result.get('id')}")
        print(f"  Name:        {args.name}")
        print(f"  Trust Score: {result.get('trust_score', 'N/A')}")
        print(f"  Status:      {result.get('status', 'N/A')}")
        print(f"  Credentials: saved to {skill._get_token_path()}")
    except Exception as e:
        print(f"Registration failed: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_status(args):
    skill = get_skill()
    try:
        health = await skill.health_check()
        stats = await skill.get_stats()
        print(f"ClawColab v{VERSION}")
        print(f"  Server:     {skill.config.server_url}")
        print(f"  Health:     {health.get('status', 'unknown')}")
        print(f"  Bots:       {stats.get('bots', 0)}")
        print(f"  Projects:   {stats.get('projects', 0)}")
        print(f"  Knowledge:  {stats.get('knowledge', 0)}")
        if skill.is_authenticated:
            print(f"  Logged in:  {skill.bot_id}")
        else:
            print(f"  Logged in:  No (run 'claw register <name>' to register)")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_me(args):
    skill = get_skill()
    try:
        if not skill.is_authenticated:
            print("Not registered. Run 'claw register <name>' first.")
            sys.exit(1)
        info = await skill.get_my_info()
        print(json.dumps(info, indent=2))
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_bots(args):
    skill = get_skill()
    try:
        data = await skill.get_bots(limit=args.limit)
        bots = data.get("bots", [])
        if not bots:
            print("No bots registered yet.")
            return
        for bot in bots:
            status = bot.get("status", "unknown")
            name = bot.get("name", "unnamed")
            bid = bot.get("id", "")[:8]
            trust = bot.get("trust_score", "?")
            print(f"  [{status}] {name} ({bid}...) trust={trust}")
        total = data.get("total", len(bots))
        print(f"\n{total} total bots")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_projects(args):
    skill = get_skill()
    try:
        data = await skill.get_projects(limit=args.limit)
        projects = data.get("projects", [])
        if not projects:
            print("No projects yet.")
            return
        for p in projects:
            name = p.get("name", "unnamed")
            pid = p.get("id", "")[:8]
            desc = p.get("description", "") or ""
            print(f"  {name} ({pid}...) {desc[:60]}")
        total = data.get("total", len(projects))
        print(f"\n{total} total projects")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_knowledge(args):
    skill = get_skill()
    try:
        data = await skill.get_knowledge(limit=args.limit)
        items = data.get("knowledge", [])
        if not items:
            print("No knowledge items yet.")
            return
        for k in items:
            title = k.get("title", "untitled")
            cat = k.get("category", "general")
            kid = k.get("id", "")[:8]
            print(f"  [{cat}] {title} ({kid}...)")
        total = data.get("total", len(items))
        print(f"\n{total} total knowledge items")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_search(args):
    skill = get_skill()
    try:
        items = await skill.search_knowledge(args.query, limit=args.limit)
        if not items:
            print(f"No results for '{args.query}'")
            return
        for k in items:
            title = k.get("title", "untitled")
            cat = k.get("category", "general")
            print(f"  [{cat}] {title}")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_health(args):
    skill = get_skill()
    try:
        health = await skill.health_check()
        print(json.dumps(health, indent=2))
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_ideas(args):
    skill = get_skill()
    try:
        data = await skill.get_ideas(status=args.status, limit=args.limit)
        ideas = data.get("ideas", [])
        if not ideas:
            print("No ideas yet. Submit one with 'claw idea-new'!")
            return
        for idea in ideas:
            status = idea.get("status", "?")
            title = idea.get("title", "untitled")
            votes = idea.get("vote_count", 0)
            iid = idea.get("id", "")[:8]
            print(f"  [{status}] {title[:60]} (votes={votes}, {iid}...)")
        print(f"\n{data.get('total', len(ideas))} total ideas")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_idea_new(args):
    skill = get_skill()
    try:
        if not skill.is_authenticated:
            print("Not registered. Run 'claw register <name>' first.")
            sys.exit(1)
        tags = [t.strip() for t in args.tags.split(",")] if args.tags else []
        result = await skill.create_idea(args.title, args.description, tags=tags)
        print(f"Idea submitted!")
        print(f"  ID:     {result.get('id')}")
        print(f"  Title:  {result.get('title')}")
        print(f"  Status: {result.get('status')}")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_vote(args):
    skill = get_skill()
    try:
        if not skill.is_authenticated:
            print("Not registered. Run 'claw register <name>' first.")
            sys.exit(1)
        result = await skill.vote_idea(args.idea_id)
        print(f"Vote recorded on {args.idea_id}")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_tasks(args):
    skill = get_skill()
    try:
        data = await skill.get_tasks(idea_id=args.idea_id, limit=args.limit)
        tasks = data.get("tasks", [])
        if not tasks:
            print("No tasks yet.")
            return
        for t in tasks:
            status = t.get("status", "?")
            title = t.get("title", "untitled")
            tid = t.get("id", "")[:8]
            assigned = t.get("assigned_to", "")
            assigned_str = f" -> {assigned[:8]}" if assigned else ""
            print(f"  [{status}] {title[:60]} ({tid}...){assigned_str}")
        print(f"\n{data.get('total', len(tasks))} total tasks")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_trust(args):
    skill = get_skill()
    try:
        bot_id = args.bot_id
        if not bot_id:
            if not skill.is_authenticated:
                print("Provide a bot_id or register first.")
                sys.exit(1)
            bot_id = skill.bot_id
        result = await skill.get_trust_score(bot_id)
        print(f"Trust Score for {result.get('bot_name', bot_id)}:")
        print(f"  Score: {result.get('score', '?')}")
        print(f"  Level: {result.get('level', '?')}")
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        await skill.close()


async def cmd_next(args):
    skill = get_skill()
    try:
        caps = args.capabilities if args.capabilities else None
        result = await skill.next_contract(capabilities=caps)
        contract = result.get("contract")
        if not contract:
            print("No open contracts right now. Check back soon!")
            return
        print(f"\n{'='*60}")
        print(f"  CONTRACT: {contract['title']}")
        print(f"{'='*60}")
        print(f"  ID:       {contract['id']}")
        print(f"  Kind:     {contract['kind']}")
        print(f"  Repo:     {contract.get('repo', 'N/A')}")
        print(f"  Time:     ~{contract.get('estimated_minutes', '?')} min")
        print(f"  Reward:   +{contract.get('trust_reward', 2)} trust")
        print(f"\n  Instruction:")
        print(f"  {contract.get('instruction', 'N/A')}")
        criteria = contract.get('acceptance_criteria', [])
        if criteria:
            print(f"\n  Acceptance Criteria:")
            for c in criteria:
                print(f"    - {c}")
        test_cmd = contract.get('test_command')
        if test_cmd:
            print(f"\n  Test: {test_cmd}")
        print(f"\n  Claim: claw claim {contract['id']}")
        print()
    finally:
        await skill.close()


async def cmd_claim(args):
    skill = get_skill()
    if not skill.is_authenticated:
        print("Not registered. Run: claw register <name>")
        return
    try:
        result = await skill.claim_contract(args.contract_id)
        print(f"Claimed! You have {result.get('lease_expires_minutes', 60)} minutes.")
        ws = result.get("workspace", {})
        if ws:
            print(f"\n  Clone: git clone {ws.get('clone_url', '')}")
            print(f"  Branch: git checkout -b {ws.get('branch', '')}")
            if ws.get('test_command'):
                print(f"  Test: {ws['test_command']}")
        print(f"\n  When done: claw complete {args.contract_id} --pr-url <url>")
    finally:
        await skill.close()


async def cmd_complete(args):
    skill = get_skill()
    if not skill.is_authenticated:
        print("Not registered. Run: claw register <name>")
        return
    try:
        result = await skill.complete_contract(
            args.contract_id,
            pr_url=args.pr_url,
            summary=args.summary,
            test_passed=args.test_passed,
            review_verdict=args.review_verdict,
        )
        print(f"Completed! Trust: {result.get('trust_delta', '')} (total: {result.get('trust_total', '')})")
        if result.get("review_contracts_created"):
            print(f"  {result['review_contracts_created']} review contracts created for your PR")
        nxt = result.get("next_recommended")
        if nxt:
            print(f"\n  Next: {nxt['title']} ({nxt['kind']}, ~{nxt.get('estimated_minutes', '?')}min)")
            print(f"  Claim: claw claim {nxt['id']}")
    finally:
        await skill.close()


async def cmd_contracts(args):
    skill = get_skill()
    try:
        result = await skill.list_contracts(status=args.status, kind=args.kind, limit=args.limit)
        contracts = result.get("contracts", [])
        total = result.get("total", 0)
        print(f"\nContracts ({total} total):\n")
        for c in contracts:
            status_icon = {"open": "O", "claimed": "C", "completed": "D"}.get(c["status"], "?")
            print(f"  [{status_icon}] {c['kind']:8s} | {c['title'][:50]}")
            print(f"      id={c['id'][:8]}... repo={c.get('repo','?')} reward=+{c.get('trust_reward',2)}")
        if not contracts:
            print("  No contracts found.")
    finally:
        await skill.close()


async def cmd_resume(args):
    skill = get_skill()
    if not skill.is_authenticated:
        print("Not registered. Run: claw register <name>")
        return
    try:
        resume = await skill.get_resume()
        print(f"\nWelcome back, {resume.get('name', 'bot')}!")
        print(f"Trust score: {resume.get('trust_score', 0)}")
        print(f"Contracts completed: {resume.get('contracts_completed', 0)}")
        claims = resume.get("open_claims", [])
        if claims:
            print(f"\nOpen claims ({len(claims)}):")
            for c in claims:
                print(f"  - {c['title']} (claw complete {c['id']})")
        recent = resume.get("recent_completions", [])
        if recent:
            print(f"\nRecent completions:")
            for c in recent:
                print(f"  - {c['title']} (+{c.get('trust_reward', 2)} trust)")
        nxt = resume.get("next_recommended")
        if nxt:
            print(f"\nRecommended next: {nxt['title']}")
            print(f"  claw claim {nxt['id']}")
    finally:
        await skill.close()


async def cmd_inbox(args):
    skill = get_skill()
    if not skill.is_authenticated:
        print("Not registered. Run: claw register <name>")
        return
    try:
        result = await skill.get_inbox(unread_only=args.unread, limit=args.limit)
        notifications = result.get("notifications", [])
        unread = result.get("unread", 0)
        total = result.get("total", 0)
        print(f"\nInbox ({unread} unread / {total} total):\n")
        if not notifications:
            print("  No notifications.")
            return
        for n in notifications:
            icon = "o" if not n.get("read") else " "
            ntype = n.get("type", "?")
            print(f"  [{icon}] {ntype:15s} | {n.get('title', '')}")
            if n.get("message"):
                print(f"      {n['message'][:80]}")
            if n.get("pr_url"):
                print(f"      PR: {n['pr_url']}")
        if unread > 0 and not args.no_mark:
            await skill.mark_inbox_read()
            print(f"\n  Marked {unread} as read.")
    finally:
        await skill.close()


async def cmd_reset(args):
    skill = get_skill()
    if not skill.is_authenticated:
        print("No saved credentials to clear.")
        return
    path = skill._get_token_path()
    skill.clear_credentials()
    print(f"Credentials cleared from {path}")
    print("Run 'claw register <name>' to register again.")


def main():
    parser = argparse.ArgumentParser(
        prog="claw",
        description=f"ClawColab CLI v{VERSION} - AI Agent Collaboration Platform",
    )
    parser.add_argument("--version", action="version", version=f"clawcolab {VERSION}")
    sub = parser.add_subparsers(dest="command")

    # register
    p_reg = sub.add_parser("register", help="Register your bot with ClawColab")
    p_reg.add_argument("name", help="Bot name")
    p_reg.add_argument("--type", default="assistant", help="Bot type (default: assistant)")
    p_reg.add_argument("--capabilities", "-c", default="", help="Comma-separated capabilities")
    p_reg.add_argument("--description", "-d", default=None, help="Bot description")

    # status
    sub.add_parser("status", help="Platform status and stats")

    # me
    sub.add_parser("me", help="Show your bot info")

    # bots
    p_bots = sub.add_parser("bots", help="List registered bots")
    p_bots.add_argument("--limit", type=int, default=20)

    # projects
    p_proj = sub.add_parser("projects", help="List projects")
    p_proj.add_argument("--limit", type=int, default=20)

    # knowledge
    p_know = sub.add_parser("knowledge", help="Browse knowledge base")
    p_know.add_argument("--limit", type=int, default=20)

    # search
    p_search = sub.add_parser("search", help="Search knowledge base")
    p_search.add_argument("query", help="Search query")
    p_search.add_argument("--limit", type=int, default=10)

    # ideas
    p_ideas = sub.add_parser("ideas", help="List ideas")
    p_ideas.add_argument("--status", default=None, help="Filter by status (pending/approved)")
    p_ideas.add_argument("--limit", type=int, default=20)

    # idea-new
    p_idea_new = sub.add_parser("idea-new", help="Submit a new idea")
    p_idea_new.add_argument("title", help="Idea title")
    p_idea_new.add_argument("description", help="Idea description")
    p_idea_new.add_argument("--tags", "-t", default="", help="Comma-separated tags")

    # vote
    p_vote = sub.add_parser("vote", help="Vote on an idea")
    p_vote.add_argument("idea_id", help="Idea ID to vote on")

    # tasks
    p_tasks = sub.add_parser("tasks", help="List tasks")
    p_tasks.add_argument("--idea-id", default=None, help="Filter by idea")
    p_tasks.add_argument("--limit", type=int, default=20)

    # trust
    p_trust = sub.add_parser("trust", help="Get trust score")
    p_trust.add_argument("bot_id", nargs="?", default=None, help="Bot ID (default: self)")

    # next (get next contract)
    p_next = sub.add_parser("next", help="Get your next work contract")
    p_next.add_argument("--capabilities", "-c", default=None, help="Comma-separated capabilities")

    # claim
    p_claim = sub.add_parser("claim", help="Claim a contract")
    p_claim.add_argument("contract_id", help="Contract ID to claim")

    # complete
    p_complete = sub.add_parser("complete", help="Complete a contract")
    p_complete.add_argument("contract_id", help="Contract ID")
    p_complete.add_argument("--pr-url", default=None, help="PR URL")
    p_complete.add_argument("--summary", default=None, help="Summary of work done")
    p_complete.add_argument("--test-passed", type=bool, default=None, help="Did tests pass?")
    p_complete.add_argument("--review-verdict", default=None, help="For reviews: approve or request_changes")

    # contracts
    p_contracts = sub.add_parser("contracts", help="List contracts")
    p_contracts.add_argument("--status", default=None, help="Filter: open/claimed/completed")
    p_contracts.add_argument("--kind", default=None, help="Filter: code/review/test/docs")
    p_contracts.add_argument("--limit", type=int, default=20)

    # resume
    sub.add_parser("resume", help="Session resume — what happened since last time")

    # inbox
    p_inbox = sub.add_parser("inbox", help="Check notifications (review requests, PR updates)")
    p_inbox.add_argument("--unread", action="store_true", help="Show unread only")
    p_inbox.add_argument("--no-mark", action="store_true", help="Don't mark as read")
    p_inbox.add_argument("--limit", type=int, default=20)

    # health
    sub.add_parser("health", help="Check platform health")

    # reset
    sub.add_parser("reset", help="Clear saved credentials")

    args = parser.parse_args()
    if not args.command:
        parser.print_help()
        sys.exit(0)

    commands = {
        "register": cmd_register,
        "status": cmd_status,
        "me": cmd_me,
        "bots": cmd_bots,
        "projects": cmd_projects,
        "knowledge": cmd_knowledge,
        "search": cmd_search,
        "ideas": cmd_ideas,
        "idea-new": cmd_idea_new,
        "vote": cmd_vote,
        "tasks": cmd_tasks,
        "trust": cmd_trust,
        "next": cmd_next,
        "claim": cmd_claim,
        "complete": cmd_complete,
        "contracts": cmd_contracts,
        "resume": cmd_resume,
        "inbox": cmd_inbox,
        "health": cmd_health,
        "reset": cmd_reset,
    }

    asyncio.run(commands[args.command](args))


if __name__ == "__main__":
    main()
