"""OmniFocus Inbox Processor — Inbox 항목 분류 + 라우팅 (LaunchAgent, 5분 주기)"""

import json
import logging
import os
import subprocess
import sys

import httpx
from dotenv import load_dotenv

load_dotenv()

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger("inbox_processor")

GPU_OLLAMA_URL = os.getenv("GPU_OLLAMA_URL", "http://192.168.1.186:11434")
CALDAV_BRIDGE_URL = os.getenv("CALDAV_BRIDGE_URL", "http://127.0.0.1:8092")
DEVONTHINK_BRIDGE_URL = os.getenv("DEVONTHINK_BRIDGE_URL", "http://127.0.0.1:8093")


def run_applescript(script: str, timeout: int = 15) -> str:
    result = subprocess.run(
        ["osascript", "-e", script],
        capture_output=True, text=True, timeout=timeout,
    )
    if result.returncode != 0:
        raise RuntimeError(f"AppleScript error: {result.stderr.strip()}")
    return result.stdout.strip()


def get_inbox_items() -> list[dict]:
    """OmniFocus Inbox에서 bot-processed 태그가 없는 항목 조회."""
    script = '''
tell application "OmniFocus"
    tell default document
        set output to ""
        set inboxTasks to every inbox task
        repeat with t in inboxTasks
            set tagNames to {}
            repeat with tg in (tags of t)
                set end of tagNames to name of tg
            end repeat
            set AppleScript's text item delimiters to ","
            set tagStr to tagNames as text
            if tagStr does not contain "bot-processed" then
                set taskId to id of t
                set taskName to name of t
                set taskNote to note of t
                set output to output & taskId & "|||" & taskName & "|||" & taskNote & "\\n"
            end if
        end repeat
        return output
    end tell
end tell'''
    try:
        result = run_applescript(script)
        items = []
        for line in result.strip().split("\n"):
            if "|||" not in line:
                continue
            parts = line.split("|||", 2)
            items.append({
                "id": parts[0].strip(),
                "name": parts[1].strip() if len(parts) > 1 else "",
                "note": parts[2].strip() if len(parts) > 2 else "",
            })
        return items
    except Exception as e:
        logger.error(f"Failed to get inbox items: {e}")
        return []


def mark_processed(task_id: str) -> None:
    """항목에 bot-processed 태그 추가."""
    script = f'''
tell application "OmniFocus"
    tell default document
        try
            set theTag to first tag whose name is "bot-processed"
        on error
            set theTag to make new tag with properties {{name:"bot-processed"}}
        end try
        set theTask to first flattened task whose id is "{task_id}"
        add theTag to tags of theTask
    end tell
end tell'''
    try:
        run_applescript(script)
        logger.info(f"Marked as processed: {task_id}")
    except Exception as e:
        logger.error(f"Failed to mark processed {task_id}: {e}")


def complete_task(task_id: str) -> None:
    """OmniFocus 항목 완료 처리."""
    script = f'''
tell application "OmniFocus"
    tell default document
        set theTask to first flattened task whose id is "{task_id}"
        mark complete theTask
    end tell
end tell'''
    try:
        run_applescript(script)
        logger.info(f"Completed: {task_id}")
    except Exception as e:
        logger.error(f"Failed to complete {task_id}: {e}")


def classify_item(name: str, note: str) -> dict:
    """Qwen 3.5로 항목 분류."""
    prompt = f"""OmniFocus Inbox 항목을 분류하세요. JSON만 출력.

{{
  "type": "calendar|note|task|reminder",
  "title": "제목/일정 이름",
  "start": "YYYY-MM-DDTHH:MM:SS (calendar/reminder일 때)",
  "location": "장소 (calendar일 때, 없으면 null)",
  "content": "메모 내용 (note일 때)"
}}

type 판단:
- calendar: 시간이 명시된 일정/약속/회의
- reminder: 알림/리마인드 (시간 기반)
- note: 메모/기록/아이디어
- task: 할 일/업무 (OmniFocus에 유지)

항목: {name}
{f'메모: {note}' if note else ''}"""

    try:
        resp = httpx.post(
            f"{GPU_OLLAMA_URL}/api/generate",
            json={"model": "id-9b:latest", "system": "/no_think", "prompt": prompt, "stream": False, "format": "json", "think": False},
            timeout=15,
        )
        return json.loads(resp.json()["response"])
    except Exception as e:
        logger.error(f"Classification failed: {e}")
        return {"type": "task", "title": name, "content": note}


def route_calendar(cls: dict, task_id: str) -> None:
    """CalDAV 브릿지로 일정 생성."""
    try:
        resp = httpx.post(
            f"{CALDAV_BRIDGE_URL}/calendar/create",
            json={
                "title": cls.get("title", ""),
                "start": cls.get("start", ""),
                "location": cls.get("location"),
            },
            timeout=10,
        )
        if resp.json().get("success"):
            logger.info(f"Calendar event created: {cls.get('title')}")
            mark_processed(task_id)
            complete_task(task_id)
        else:
            logger.error(f"Calendar create failed: {resp.text[:200]}")
            mark_processed(task_id)
    except Exception as e:
        logger.error(f"Calendar routing failed: {e}")
        mark_processed(task_id)


def route_note(cls: dict, task_id: str) -> None:
    """DEVONthink 브릿지로 메모 저장."""
    content = cls.get("content") or cls.get("title", "")
    title = cls.get("title", "OmniFocus 메모")

    try:
        resp = httpx.post(
            f"{DEVONTHINK_BRIDGE_URL}/save",
            json={
                "title": title,
                "content": content,
                "type": "markdown",
                "tags": ["omnifocus", "inbox"],
            },
            timeout=10,
        )
        if resp.json().get("success"):
            logger.info(f"Note saved to DEVONthink: {title}")
        mark_processed(task_id)
        complete_task(task_id)
    except Exception as e:
        logger.error(f"Note routing failed: {e}")
        mark_processed(task_id)


def route_task(cls: dict, task_id: str) -> None:
    """Task는 OmniFocus에 유지. 태그만 추가."""
    mark_processed(task_id)
    logger.info(f"Task kept in OmniFocus: {cls.get('title', '')}")


def main():
    logger.info("Inbox processor started")

    items = get_inbox_items()
    if not items:
        logger.info("No unprocessed inbox items")
        return

    logger.info(f"Processing {len(items)} inbox items")

    for item in items:
        logger.info(f"Processing: {item['name']}")
        cls = classify_item(item["name"], item["note"])
        item_type = cls.get("type", "task")

        if item_type == "calendar" or item_type == "reminder":
            route_calendar(cls, item["id"])
        elif item_type == "note":
            route_note(cls, item["id"])
        else:  # task
            route_task(cls, item["id"])

    logger.info("Inbox processing complete")


if __name__ == "__main__":
    main()
