#!/usr/bin/env python3
"""
自然语言日程录入工具。

Agent 将用户的自然语言解析为结构化字段后，调用此脚本写入 Google Calendar，
并可选择性地立即在 OpenClaw Cron 中注册提醒任务。

用法：
  # 基本：只指定开始时间，持续时间默认 60 分钟
  python3 apps/add_event.py \\
    --summary "客户会议" \\
    --date "2026-03-31" \\
    --start "14:00"

  # 完整：指定结束时间 + 地点 + 备注
  python3 apps/add_event.py \\
    --summary "产品评审" \\
    --date "2026-04-02" \\
    --start "10:00" \\
    --end "11:30" \\
    --location "线上" \\
    --description "Q2 规划讨论" \\
    --remind 15

  # 只指定时长（分钟）而非结束时间
  python3 apps/add_event.py \\
    --summary "跑步" \\
    --date "2026-04-01" \\
    --start "07:00" \\
    --duration 45

  # 干运行（不写 GCal，只打印 payload）
  python3 apps/add_event.py \\
    --summary "测试事件" \\
    --date "2026-04-01" \\
    --start "10:00" \\
    --dry-run

输出（JSON，供 Agent 读取）：
  成功：{"ok": true,  "event_id": "xxx", "summary": "...", "start": "...", "end": "..."}
  失败：{"ok": false, "error": "..."}
"""

from __future__ import annotations

import argparse
import json
import logging
import sys
from datetime import datetime, timedelta
from pathlib import Path

# ── sys.path ─────────────────────────────────────────────────────
sys.path.insert(0, str(Path(__file__).parent.parent))

from config.settings import TIMEZONE
from gcal.client import CalendarAPIError, CalendarAuthError
from services.calendar_backend import active_provider, create_event as backend_create_event
from services.datetime_utils import (
    DateTimeValidationError,
    build_event_range,
    parse_local_date,
    parse_local_time,
)
from services.job_store import append_job_if_absent
from services.task_builder import build_reminder_task, build_reminder_task_name

logging.basicConfig(level=logging.WARNING, format="%(levelname)s %(message)s")
logger = logging.getLogger(__name__)


# ─────────────────────────── 时间解析 ────────────────────────────

def parse_date(date_str: str, tz: str) -> datetime:
    return parse_local_date(date_str, tz)


def parse_time(time_str: str, base_date: datetime) -> datetime:
    return parse_local_time(time_str, base_date)


# ─────────────────────────── 提醒注册 ────────────────────────────

def _register_reminder(
    summary: str,
    start: datetime,
    lead_minutes: int,
    dry_run: bool,
    event_id: str = "",
) -> dict:
    """
    将提醒任务注册到 OpenClaw Cron（jobs.json）。

    返回状态字典：
    {
        "registered": bool,      # 是否成功注册
        "existed": bool,         # 是否已存在
        "error": str or None     # 错误信息（如果有）
    }
    """
    from datetime import timezone

    remind_at_utc = (start - timedelta(minutes=lead_minutes)).astimezone(timezone.utc)
    name = build_reminder_task_name(summary, start, event_id)
    payload = build_reminder_task(
        name=name,
        remind_at_utc=remind_at_utc,
        message=(
            f"⏰ **{summary}** 将在 {lead_minutes} 分钟后开始\n"
            f"🕐 {start.strftime('%H:%M')}"
        ),
    )

    if dry_run:
        print(f"[dry-run] 将注册提醒任务: {name}（{remind_at_utc.strftime('%H:%M')} UTC）",
              file=sys.stderr)
        return {"registered": True, "existed": False, "error": None}

    try:
        if append_job_if_absent(payload):
            logger.warning(f"✅ 提醒任务已注册: {name}")
            return {"registered": True, "existed": False, "error": None}
        else:
            logger.warning(f"⏭️  提醒任务已存在，跳过: {name}")
            return {"registered": True, "existed": True, "error": None}
    except Exception as e:
        error_msg = str(e)
        logger.warning(f"注册提醒失败（不影响日历写入）: {error_msg}")
        return {"registered": False, "existed": False, "error": error_msg}


# ─────────────────────────── main ─────────────────────────────────

def main() -> None:
    parser = argparse.ArgumentParser(
        description="将结构化日程信息写入 Google Calendar",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument("--summary",     required=True,  help="事件标题")
    parser.add_argument("--date",        required=True,  help="日期 YYYY-MM-DD")
    parser.add_argument("--start",       required=True,  help="开始时间 HH:MM")
    parser.add_argument("--end",                         help="结束时间 HH:MM（与 --duration 二选一）")
    parser.add_argument("--duration",    type=int, default=60,
                        help="持续时间（分钟，默认 60）；--end 优先")
    parser.add_argument("--location",    default="",     help="地点（可选）")
    parser.add_argument("--description", default="",     help="备注（可选）")
    parser.add_argument("--remind",      type=int, default=0,
                        help="提前提醒分钟数（0 = 不注册提醒，默认 0）")
    parser.add_argument("--dry-run",     action="store_true",
                        help="只打印 payload，不写入 Google Calendar")
    args = parser.parse_args()

    def _fail(msg: str) -> None:
        print(json.dumps({"ok": False, "error": msg}, ensure_ascii=False))
        sys.exit(1)

    # ── 1. 解析时间 ───────────────────────────────────────────────
    try:
        start, end = build_event_range(
            args.date,
            args.start,
            args.end,
            args.duration,
            TIMEZONE,
        )
    except DateTimeValidationError as e:
        _fail(str(e))
        return

    # ── 2. dry-run ────────────────────────────────────────────────
    payload_preview = {
        "summary":     args.summary,
        "date":        args.date,
        "start":       start.strftime("%H:%M"),
        "end":         end.strftime("%H:%M"),
        "duration_min": int((end - start).total_seconds() / 60),
        "location":    args.location,
        "description": args.description,
        "remind_min":  args.remind,
    }
    if args.dry_run:
        print(json.dumps(
            {
                "ok": True,
                "dry_run": True,
                "provider": active_provider(),
                "payload": payload_preview,
            },
            ensure_ascii=False, indent=2,
        ))
        if args.remind > 0:
            _register_reminder(args.summary, start, args.remind, dry_run=True)
        return

    # ── 3. 写入当前事件后端 ───────────────────────────────────────
    try:
        created = backend_create_event(
            summary=args.summary,
            start=start,
            end=end,
            location=args.location,
            description=args.description,
            remind_minutes=args.remind,
        )
    except (CalendarAuthError, CalendarAPIError) as e:
        _fail(str(e))
        return

    # ── 4. 可选：注册提醒 ─────────────────────────────────────────
    reminder_status = {"registered": False, "existed": False, "error": None}
    if args.remind > 0:
        reminder_status = _register_reminder(
            args.summary, start, args.remind, dry_run=False, event_id=created.event_id
        )

    # ── 5. 输出结果 ───────────────────────────────────────────────
    result = {
        "ok":                     True,
        "provider":               created.provider,
        "sync_state":             created.sync_state,
        "event_id":               created.event_id,
        "summary":                args.summary,
        "date":                   args.date,
        "start":                  start.strftime("%H:%M"),
        "end":                    end.strftime("%H:%M"),
        "duration_min":           int((end - start).total_seconds() / 60),
        "location":               args.location,
        "remind_min":             args.remind,
        "reminder_registered":    reminder_status["registered"],
        "reminder_existed":       reminder_status["existed"],
        "reminder_error":         reminder_status["error"],
    }
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
