# 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

"""
Clockify Time Tracking Skill

Start/stop timers, log time entries, and generate reports.

Setup:
    CLOCKIFY_API_KEY=your_api_key
    CLOCKIFY_WORKSPACE_ID=your_workspace_id

Get a key at: https://clockify.me/user/preferences#advanced
API: https://api.clockify.me/api/v1/
"""

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.clockify.me/api/v1"


def _api_key() -> str:
    return get_env("CLOCKIFY_API_KEY") or ""


def _workspace_id() -> str:
    return get_env("CLOCKIFY_WORKSPACE_ID") or ""


def _headers() -> dict:
    return {"X-Api-Key": _api_key(), "Content-Type": "application/json"}


def _check_config() -> str:
    if not _api_key():
        return (
            "Clockify not configured.\n"
            "Set CLOCKIFY_API_KEY in your environment.\n"
            "Get a key at: https://clockify.me/user/preferences#advanced"
        )
    if not _workspace_id():
        return "CLOCKIFY_WORKSPACE_ID not set."
    return ""


def _user_id() -> str:
    """Get current user ID."""
    try:
        result = api_get(
            f"{BASE_URL}/user",
            headers=_headers(),
            service_name="Clockify",
        )
        return result.get("id", "")
    except Exception:
        return ""


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


def start_timer(data: dict) -> str:
    """Start a time tracking timer."""
    err = _check_config()
    if err:
        return err

    description = data.get("description", "").strip()
    if not description:
        return "Please provide a description for the timer."

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

    try:
        import datetime

        body = {
            "start": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
            "description": description,
        }
        if project_id:
            body["projectId"] = project_id

        ws = _workspace_id()
        result = api_post(
            f"{BASE_URL}/workspaces/{ws}/time-entries",
            json=body,
            headers=_headers(),
            service_name="Clockify",
        )

        entry_id = result.get("id", "")
        return (
            f"**Timer started!**\n\n"
            f"  Entry ID: {entry_id}\n"
            f"  Description: {description}\n\n"
            "Use `stop_timer` to stop tracking."
        )

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Clockify start timer error: %s", e)
        return f"Error starting timer: {e}"


def stop_timer(data: dict) -> str:
    """Stop the currently running timer."""
    err = _check_config()
    if err:
        return err

    try:
        import datetime

        user_id = _user_id()
        if not user_id:
            return "Could not determine Clockify user ID."

        ws = _workspace_id()
        result = api_post(
            f"{BASE_URL}/workspaces/{ws}/user/{user_id}/time-entries",
            json={
                "end": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
            },
            headers=_headers(),
            service_name="Clockify",
        )

        description = result.get("description", "")
        duration = result.get("timeInterval", {}).get("duration", "")

        return f"**Timer stopped!**\n\n  Description: {description}\n  Duration: {duration}"

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Clockify stop timer error: %s", e)
        return f"Error stopping timer: {e}"


def log_time(data: dict) -> str:
    """Log a completed time entry."""
    err = _check_config()
    if err:
        return err

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

    start = data.get("start", "").strip()
    end = data.get("end", "").strip()
    if not start or not end:
        return "Please provide start and end times (ISO format)."

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

    try:
        body = {
            "start": start,
            "end": end,
            "description": description,
        }
        if project_id:
            body["projectId"] = project_id

        ws = _workspace_id()
        result = api_post(
            f"{BASE_URL}/workspaces/{ws}/time-entries",
            json=body,
            headers=_headers(),
            service_name="Clockify",
        )

        entry_id = result.get("id", "")
        duration = result.get("timeInterval", {}).get("duration", "")

        return (
            f"**Time logged!**\n\n"
            f"  Entry ID: {entry_id}\n"
            f"  Description: {description}\n"
            f"  Duration: {duration}"
        )

    except APIError as e:
        return str(e)
    except Exception as e:
        logger.error("Clockify log time error: %s", e)
        return f"Error logging time: {e}"


def time_report(data: dict) -> str:
    """Get recent time entries."""
    err = _check_config()
    if err:
        return err

    limit = min(int(data.get("limit", 20)), 50)

    try:
        user_id = _user_id()
        if not user_id:
            return "Could not determine Clockify user ID."

        ws = _workspace_id()
        result = _time_entries_cached(ws, user_id, limit)

        if not result:
            return "No time entries found."

        lines = [f"**Recent Time Entries** ({len(result)}):", ""]

        for i, entry in enumerate(result, 1):
            description = entry.get("description", "No description")
            interval = entry.get("timeInterval", {})
            start = interval.get("start", "")[:16]
            duration_str = interval.get("duration", "")
            project = entry.get("project", {})
            project_name = project.get("name", "") if project else ""

            lines.append(f"{i}. **{description}**")
            details = []
            if start:
                details.append(start)
            if duration_str:
                details.append(duration_str)
            if project_name:
                details.append(project_name)
            if details:
                lines.append(f"   {' | '.join(details)}")
            lines.append("")

        return "\n".join(lines)

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


@cached(prefix="clockify_entries", ttl=60)
def _time_entries_cached(workspace_id: str, user_id: str, limit: int) -> list:
    return api_get(
        f"{BASE_URL}/workspaces/{workspace_id}/user/{user_id}/time-entries",
        params={"page-size": limit},
        headers=_headers(),
        service_name="Clockify",
    )


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

    try:
        ws = _workspace_id()
        result = _projects_cached(ws)

        if not result:
            return "No projects found."

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

        for i, p in enumerate(result, 1):
            name = p.get("name", "")
            pid = p.get("id", "")
            client = p.get("clientName", "")

            lines.append(f"{i}. **{name}** (ID: {pid})")
            if client:
                lines.append(f"   Client: {client}")
            lines.append("")

        return "\n".join(lines)

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


@cached(prefix="clockify_projects", ttl=300)
def _projects_cached(workspace_id: str) -> list:
    return api_get(
        f"{BASE_URL}/workspaces/{workspace_id}/projects",
        headers=_headers(),
        service_name="Clockify",
    )


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

TOOLS = [
    {
        "name": "start_timer",
        "description": "Start a Clockify time tracking timer with a description.",
        "input_schema": {
            "type": "object",
            "properties": {
                "description": {"type": "string", "description": "What you're working on"},
                "project_id": {"type": "string", "description": "Optional project ID"},
            },
            "required": ["description"],
        },
        "handler": start_timer,
        "category": "clockify",
    },
    {
        "name": "stop_timer",
        "description": "Stop the currently running Clockify timer.",
        "input_schema": {"type": "object", "properties": {}},
        "handler": stop_timer,
        "category": "clockify",
    },
    {
        "name": "log_time",
        "description": "Log a completed time entry with start/end times.",
        "input_schema": {
            "type": "object",
            "properties": {
                "description": {"type": "string", "description": "Description of the work"},
                "start": {"type": "string", "description": "Start time (ISO 8601)"},
                "end": {"type": "string", "description": "End time (ISO 8601)"},
                "project_id": {"type": "string", "description": "Optional project ID"},
            },
            "required": ["description", "start", "end"],
        },
        "handler": log_time,
        "category": "clockify",
    },
    {
        "name": "time_report",
        "description": "View recent Clockify time entries with durations and projects.",
        "input_schema": {
            "type": "object",
            "properties": {
                "limit": {
                    "type": "integer",
                    "description": "Max entries (1-50, default 20)",
                    "default": 20,
                },
            },
        },
        "handler": time_report,
        "category": "clockify",
    },
    {
        "name": "clockify_projects",
        "description": "List Clockify projects with client info.",
        "input_schema": {"type": "object", "properties": {}},
        "handler": clockify_projects,
        "category": "clockify",
    },
]
