# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""
Todoist Task Management Skill

Manage tasks and projects via the Todoist REST API.

Setup:
    TODOIST_API_TOKEN=your_token

Get a token at: https://todoist.com/app/settings/integrations/developer
API: https://api.todoist.com/rest/v2/
"""

import logging

from familiar.core.api_cache import cached
from familiar.skills._api_utils import (
    APIError,
    api_get,
    api_post,
    get_env,
)

logger = logging.getLogger(__name__)

BASE_URL = "https://api.todoist.com/rest/v2"


def _token() -> str:
    return get_env("TODOIST_API_TOKEN") or ""


def _headers() -> dict:
    return {"Authorization": f"Bearer {_token()}"}


def _check_config() -> str:
    if not _token():
        return (
            "Todoist not configured.\n"
            "Set TODOIST_API_TOKEN in your environment.\n"
            "Get a token at: https://todoist.com/app/settings/integrations/developer"
        )
    return ""


# ---------------------------------------------------------------------------
# Tool handlers
# ---------------------------------------------------------------------------


def todoist_tasks(data: dict) -> str:
    """List active tasks."""
    err = _check_config()
    if err:
        return err

    project_id = data.get("project_id", "")
    filter_str = data.get("filter", "")

    try:
        result = _tasks_cached(project_id, filter_str)

        if not result:
            return "No active tasks found."

        lines = [f"**Active Tasks** ({len(result)}):", ""]

        for i, t in enumerate(result, 1):
            content = t.get("content", "")
            priority = t.get("priority", 1)
            due = t.get("due", {})
            due_str = due.get("date", "") if due else ""
            labels = t.get("labels", [])
            tid = t.get("id", "")

            priority_map = {4: "P1", 3: "P2", 2: "P3", 1: "P4"}
            pri_str = priority_map.get(priority, "")

            lines.append(f"{i}. **{content}** [{pri_str}]")
            details = [f"ID: {tid}"]
            if due_str:
                details.append(f"Due: {due_str}")
            if labels:
                details.append(f"Labels: {', '.join(labels)}")
            lines.append(f"   {' | '.join(details)}")
            lines.append("")

        return "\n".join(lines)

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Todoist tasks error: %s", e)
        return f"Error fetching tasks: {e}"


@cached(prefix="todoist_tasks", ttl=60)
def _tasks_cached(project_id: str, filter_str: str) -> list:
    params = {}
    if project_id:
        params["project_id"] = project_id
    if filter_str:
        params["filter"] = filter_str
    return api_get(
        f"{BASE_URL}/tasks",
        params=params,
        headers=_headers(),
        service_name="Todoist",
    )


def todoist_add_task(data: dict) -> str:
    """Create a new task."""
    err = _check_config()
    if err:
        return err

    content = data.get("content", "").strip()
    if not content:
        return "Please provide task content."

    due_string = data.get("due_string", "").strip()
    priority = int(data.get("priority", 1))
    project_id = data.get("project_id", "")
    labels = data.get("labels", [])

    try:
        body = {"content": content, "priority": priority}
        if due_string:
            body["due_string"] = due_string
        if project_id:
            body["project_id"] = project_id
        if labels:
            if isinstance(labels, str):
                labels = [lab.strip() for lab in labels.split(",")]
            body["labels"] = labels

        result = api_post(
            f"{BASE_URL}/tasks",
            json=body,
            headers=_headers(),
            service_name="Todoist",
        )

        tid = result.get("id", "")
        url = result.get("url", "")

        lines = [
            "**Task created!**",
            "",
            f"  ID: {tid}",
            f"  Content: {content}",
        ]
        if due_string:
            lines.append(f"  Due: {due_string}")
        if url:
            lines.append(f"  URL: {url}")

        return "\n".join(lines)

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Todoist add task error: %s", e)
        return f"Error creating task: {e}"


def todoist_complete(data: dict) -> str:
    """Complete/close a task."""
    err = _check_config()
    if err:
        return err

    task_id = data.get("task_id", "").strip()
    if not task_id:
        return "Please provide a task_id to complete."

    try:
        api_post(
            f"{BASE_URL}/tasks/{task_id}/close",
            json={},
            headers=_headers(),
            service_name="Todoist",
        )

        return f"**Task {task_id} completed!**"

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Todoist complete error: %s", e)
        return f"Error completing task: {e}"


def todoist_projects(data: dict) -> str:
    """List Todoist projects."""
    err = _check_config()
    if err:
        return err

    try:
        result = _projects_cached()

        if not result:
            return "No projects found."

        lines = [f"**Projects** ({len(result)}):", ""]

        for i, p in enumerate(result, 1):
            name = p.get("name", "")
            pid = p.get("id", "")
            is_favorite = p.get("is_favorite", False)
            fav_mark = " *" if is_favorite else ""

            lines.append(f"{i}. **{name}**{fav_mark} (ID: {pid})")
            lines.append("")

        return "\n".join(lines)

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Todoist projects error: %s", e)
        return f"Error fetching projects: {e}"


@cached(prefix="todoist_projects", ttl=300)
def _projects_cached() -> list:
    return api_get(
        f"{BASE_URL}/projects",
        headers=_headers(),
        service_name="Todoist",
    )


# ---------------------------------------------------------------------------
# Tool definitions
# ---------------------------------------------------------------------------

TOOLS = [
    {
        "name": "todoist_tasks",
        "description": "List active Todoist tasks with priority, due dates, and labels.",
        "input_schema": {
            "type": "object",
            "properties": {
                "project_id": {"type": "string", "description": "Filter by project ID"},
                "filter": {"type": "string", "description": "Todoist filter string"},
            },
        },
        "handler": todoist_tasks,
        "category": "todoist",
    },
    {
        "name": "todoist_add_task",
        "description": "Create a new task in Todoist with optional due date and priority.",
        "input_schema": {
            "type": "object",
            "properties": {
                "content": {"type": "string", "description": "Task content"},
                "due_string": {
                    "type": "string",
                    "description": "Due date: 'today', 'tomorrow', 'next monday'",
                },
                "priority": {
                    "type": "integer",
                    "description": "Priority 1-4 (4=highest)",
                    "default": 1,
                },
                "project_id": {"type": "string", "description": "Target project ID"},
                "labels": {"type": "string", "description": "Comma-separated labels"},
            },
            "required": ["content"],
        },
        "handler": todoist_add_task,
        "category": "todoist",
    },
    {
        "name": "todoist_complete",
        "description": "Mark a Todoist task as completed.",
        "input_schema": {
            "type": "object",
            "properties": {
                "task_id": {"type": "string", "description": "Task ID to complete"},
            },
            "required": ["task_id"],
        },
        "handler": todoist_complete,
        "category": "todoist",
    },
    {
        "name": "todoist_projects",
        "description": "List Todoist projects.",
        "input_schema": {"type": "object", "properties": {}},
        "handler": todoist_projects,
        "category": "todoist",
    },
]
