#!/usr/bin/env python3
"""
Claude Code TASKS Skill
========================
Skill for leveraging Claude Code's native TASKS feature for multi-session coordination.

TASKS replaces TodoWrite for complex projects requiring:
- Persistence between sessions
- Task dependencies
- Multi-agent collaboration
- Cross-session updates

Source: https://www.youtube.com/watch?v=Qh6jg3FymXY
"""

import os
import json
from pathlib import Path
from typing import List, Dict, Optional
from dataclasses import dataclass, asdict
from datetime import datetime


@dataclass
class Task:
    """Represents a Claude Code Task."""
    id: str
    title: str
    description: str
    status: str = "pending"  # pending, in_progress, completed
    dependencies: List[str] = None
    assigned_to: Optional[str] = None  # session/agent identifier
    created_at: str = None
    completed_at: Optional[str] = None

    def __post_init__(self):
        if self.dependencies is None:
            self.dependencies = []
        if self.created_at is None:
            self.created_at = datetime.now().isoformat()


class ClaudeCodeTasksSkill:
    """
    Skill for managing Claude Code TASKS.

    Key Features:
    - File-system persistence (~/.claude/tasks)
    - Dependency tracking
    - Multi-session coordination via CLAUDE_CODE_TASK_LIST_ID
    """

    TASKS_DIR = Path.home() / ".claude" / "tasks"

    def __init__(self, task_list_id: str = None):
        """
        Initialize the TASKS skill.

        Args:
            task_list_id: Shared task list ID for multi-session coordination.
                         If not provided, checks CLAUDE_CODE_TASK_LIST_ID env var.
        """
        self.task_list_id = task_list_id or os.getenv("CLAUDE_CODE_TASK_LIST_ID", "default")
        self.tasks_file = self.TASKS_DIR / f"{self.task_list_id}.json"
        self._ensure_dir()

    def _ensure_dir(self):
        """Ensure tasks directory exists."""
        self.TASKS_DIR.mkdir(parents=True, exist_ok=True)

    def _load_tasks(self) -> List[Task]:
        """Load tasks from file."""
        if not self.tasks_file.exists():
            return []

        with open(self.tasks_file, 'r') as f:
            data = json.load(f)

        return [Task(**t) for t in data.get("tasks", [])]

    def _save_tasks(self, tasks: List[Task]):
        """Save tasks to file."""
        data = {
            "task_list_id": self.task_list_id,
            "updated_at": datetime.now().isoformat(),
            "tasks": [asdict(t) for t in tasks]
        }

        with open(self.tasks_file, 'w') as f:
            json.dump(data, f, indent=2)

    def add_task(self, title: str, description: str, dependencies: List[str] = None) -> Task:
        """
        Add a new task to the list.

        Args:
            title: Task title
            description: Task description
            dependencies: List of task IDs this task depends on

        Returns:
            The created Task
        """
        tasks = self._load_tasks()

        # Generate ID
        task_id = f"task_{len(tasks) + 1:03d}"

        task = Task(
            id=task_id,
            title=title,
            description=description,
            dependencies=dependencies or []
        )

        tasks.append(task)
        self._save_tasks(tasks)

        return task

    def update_status(self, task_id: str, status: str, assigned_to: str = None):
        """
        Update task status.

        Args:
            task_id: Task ID to update
            status: New status (pending, in_progress, completed)
            assigned_to: Optional session/agent identifier
        """
        tasks = self._load_tasks()

        for task in tasks:
            if task.id == task_id:
                task.status = status
                if assigned_to:
                    task.assigned_to = assigned_to
                if status == "completed":
                    task.completed_at = datetime.now().isoformat()
                break

        self._save_tasks(tasks)

    def get_available_tasks(self) -> List[Task]:
        """
        Get tasks that are ready to work on (dependencies satisfied).

        Returns:
            List of tasks with all dependencies completed
        """
        tasks = self._load_tasks()
        completed_ids = {t.id for t in tasks if t.status == "completed"}

        available = []
        for task in tasks:
            if task.status == "pending":
                deps_satisfied = all(d in completed_ids for d in task.dependencies)
                if deps_satisfied:
                    available.append(task)

        return available

    def get_task_tree(self) -> Dict:
        """
        Get task dependency tree for visualization.

        Returns:
            Dictionary with task tree structure
        """
        tasks = self._load_tasks()

        return {
            "task_list_id": self.task_list_id,
            "total": len(tasks),
            "completed": sum(1 for t in tasks if t.status == "completed"),
            "in_progress": sum(1 for t in tasks if t.status == "in_progress"),
            "pending": sum(1 for t in tasks if t.status == "pending"),
            "tasks": [asdict(t) for t in tasks]
        }

    @staticmethod
    def setup_multi_session(task_list_id: str) -> str:
        """
        Generate shell command to set up multi-session coordination.

        Args:
            task_list_id: Shared task list identifier

        Returns:
            Shell command to export environment variable
        """
        return f'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"'

    @staticmethod
    def when_to_use_tasks() -> Dict:
        """
        Return guidance on when to use TASKS vs simple prompts.

        Returns:
            Dictionary with use cases
        """
        return {
            "use_tasks_for": [
                "Full features across multiple files",
                "Large refactors spanning codebase",
                "Test suite creation",
                "Multi-session coordination",
                "Projects requiring dependency tracking",
                "Work that spans multiple Claude Code sessions"
            ],
            "skip_tasks_for": [
                "Single function refactors",
                "Simple bug fixes",
                "Quick questions",
                "Single-file changes",
                "Tasks Claude can complete in one shot"
            ],
            "key_insight": "Opus 4.5 is smart enough for simple tasks without task management. Reserve TASKS for complex coordination."
        }


# Genesis-specific utilities
def setup_genesis_task_coordination():
    """
    Set up TASKS coordination for Genesis 4-terminal setup.

    Returns:
        Commands to run in each tmux terminal
    """
    task_list_id = f"genesis-{datetime.now().strftime('%Y%m%d')}"

    return {
        "task_list_id": task_list_id,
        "setup_command": f'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"',
        "tmux_commands": [
            f'tmux send-keys -t genesis:claude1 \'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"\' Enter',
            f'tmux send-keys -t genesis:claude2 \'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"\' Enter',
            f'tmux send-keys -t genesis:claude3 \'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"\' Enter',
            f'tmux send-keys -t genesis:claude4 \'export CLAUDE_CODE_TASK_LIST_ID="{task_list_id}"\' Enter',
        ],
        "note": "All 4 Claude terminals will now share the same task list"
    }


if __name__ == "__main__":
    # Demo usage
    skill = ClaudeCodeTasksSkill(task_list_id="demo")

    print("=== Claude Code TASKS Skill Demo ===\n")

    # Show when to use
    guidance = skill.when_to_use_tasks()
    print("When to use TASKS:")
    for use in guidance["use_tasks_for"][:3]:
        print(f"  + {use}")

    print("\nSkip TASKS for:")
    for skip in guidance["skip_tasks_for"][:3]:
        print(f"  - {skip}")

    print(f"\nKey insight: {guidance['key_insight']}")

    # Genesis setup
    print("\n=== Genesis Multi-Terminal Setup ===")
    setup = setup_genesis_task_coordination()
    print(f"Task List ID: {setup['task_list_id']}")
    print(f"Setup: {setup['setup_command']}")
