#!/usr/bin/env python3
"""
Claude Board TODO Sync Hook

PostToolUse hook that syncs task tool calls to the Claude Board server.
This allows the web UI to display the current TODO list.

Handles both:
- Legacy TodoWrite (full list replacement)
- New TaskCreate/TaskUpdate (incremental operations)

This hook is non-blocking and doesn't interfere with Claude Code
if the server is unavailable.
"""

import json
import os
import sys
import urllib.error
import urllib.request

# Server configuration - can be overridden by environment variables
SERVER_HOST = os.environ.get("CLAUDE_BOARD_HOST", "127.0.0.1")
SERVER_PORT = int(os.environ.get("CLAUDE_BOARD_PORT", "8765"))
SERVER_BASE = f"http://{SERVER_HOST}:{SERVER_PORT}"
TIMEOUT = 5  # Short timeout - don't block Claude Code

# Tool names we handle
TASK_TOOLS = {"TaskCreate", "TaskUpdate", "TodoWrite"}


def send_to_server(url: str, payload: dict) -> None:
    """Send JSON payload to server, silently ignoring errors."""
    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=data,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=TIMEOUT):
            pass
    except (urllib.error.URLError, TimeoutError, OSError):
        pass


def handle_todo_write(input_data: dict) -> None:
    """Handle legacy TodoWrite - sends full list."""
    tool_input = input_data.get("tool_input", {})
    todos = tool_input.get("todos", [])
    if not todos:
        return

    project_path = input_data.get("cwd", "") or os.getcwd()
    session_id = input_data.get("session_id", "")

    send_to_server(f"{SERVER_BASE}/api/todos", {
        "todos": todos,
        "project_path": project_path,
        "session_id": session_id,
    })


def handle_task_create(input_data: dict) -> None:
    """Handle TaskCreate - sends incremental add."""
    tool_input = input_data.get("tool_input", {})
    subject = tool_input.get("subject", "")
    if not subject:
        return

    project_path = input_data.get("cwd", "") or os.getcwd()
    session_id = input_data.get("session_id", "")

    send_to_server(f"{SERVER_BASE}/api/todos/task", {
        "action": "create",
        "subject": subject,
        "description": tool_input.get("description", ""),
        "activeForm": tool_input.get("activeForm", ""),
        "project_path": project_path,
        "session_id": session_id,
    })


def handle_task_update(input_data: dict) -> None:
    """Handle TaskUpdate - sends incremental update."""
    tool_input = input_data.get("tool_input", {})
    task_id = tool_input.get("taskId", "")
    if not task_id:
        return

    project_path = input_data.get("cwd", "") or os.getcwd()
    session_id = input_data.get("session_id", "")

    payload: dict[str, object] = {
        "action": "update",
        "taskId": task_id,
        "project_path": project_path,
        "session_id": session_id,
    }

    # Include only fields that are being updated
    for field in ("status", "subject", "description", "activeForm"):
        if field in tool_input:
            payload[field] = tool_input[field]

    send_to_server(f"{SERVER_BASE}/api/todos/task", payload)


def main():
    try:
        input_data = json.load(sys.stdin)

        hook_event = input_data.get("hook_event_name", "")
        tool_name = input_data.get("tool_name", "")

        if hook_event != "PostToolUse" or tool_name not in TASK_TOOLS:
            sys.exit(0)

        if tool_name == "TodoWrite":
            handle_todo_write(input_data)
        elif tool_name == "TaskCreate":
            handle_task_create(input_data)
        elif tool_name == "TaskUpdate":
            handle_task_update(input_data)

    except Exception:
        # Don't interfere with Claude Code on any error
        pass

    sys.exit(0)


if __name__ == "__main__":
    main()
