"""Create demo business data with the API; uses only the Python standard library."""
from __future__ import annotations

import argparse
import getpass
import json
from datetime import datetime, timedelta, timezone
from http.cookiejar import CookieJar
from urllib.error import HTTPError
from urllib.parse import urlencode
from urllib.request import HTTPCookieProcessor, Request, build_opener


class ApiClient:
    def __init__(self, base: str):
        self.base = base.rstrip("/")
        self.cookies = CookieJar()
        self.opener = build_opener(HTTPCookieProcessor(self.cookies))
        self.csrf = ""

    def request(self, method: str, path: str, body: dict | None = None):
        headers = {"Accept": "application/json"}
        data = None
        if body is not None:
            headers["Content-Type"] = "application/json"
            data = json.dumps(body, ensure_ascii=False).encode("utf-8")
        if method not in {"GET", "HEAD", "OPTIONS"} and self.csrf:
            headers["X-CSRF-Token"] = self.csrf
        req = Request(self.base + path, data=data, headers=headers, method=method)
        try:
            with self.opener.open(req, timeout=30) as response:
                return json.load(response)
        except HTTPError as error:
            detail = json.loads(error.read().decode("utf-8")).get("detail", "请求失败")
            raise RuntimeError(f"HTTP {error.code}: {detail}") from None

    def login(self, username: str, password: str):
        result = self.request("POST", "/api/auth/login", {"username": username, "password": password})
        self.csrf = result["csrfToken"]
        # Login responses contain credentials; do not print them.

    def login_totp(self, username: str, code: str):
        result = self.request("POST", "/api/auth/totp/login", {"username": username, "code": code})
        self.csrf = result["csrfToken"]


def create_demo(client: ApiClient, day: str | None = None):
    day = day or datetime.now(timezone(timedelta(hours=8))).date().isoformat()
    task = client.request("POST", "/api/tasks", {
        "name": "API示例：阅读计划", "description": "由API示例创建，可在界面继续编辑。",
        "startDate": None, "endDate": None, "priority": 3, "state": "active",
        "metrics": [
            {"name": "阅读打卡", "kind": "checkin", "period": "day", "target": 1},
            {"name": "阅读页数", "kind": "quantity", "period": "week", "target": 100, "unit": "页"},
            {"name": "学习时长", "kind": "duration", "period": "week", "target": 7200, "durationUnit": "hour"},
        ],
    })
    task_id = task["taskId"]
    checkin_id, quantity_id, duration_id = [metric["metricId"] for metric in task["metrics"]]
    path = f"/api/tasks/{task_id}/daily/{day}"
    previous = client.request("GET", path)
    record = client.request("PUT", path, {
        "expectedVersion": previous["version"], "note": "读了18页，学习1小时30分钟。下一步整理笔记。",
        "completedAt": f"{day}T20:30:00+08:00",
        "values": [
            {"metricId": checkin_id, "value": 1},
            {"metricId": quantity_id, "value": 18},
            {"metricId": duration_id, "value": 5400},
        ],
    })
    summary = client.request("GET", f"/api/tasks/{task_id}/summary?{urlencode({'date': day})}")
    schedule = client.request("POST", "/api/schedules", {
        "title": "API示例：整理阅读笔记", "date": day, "time": "20:30",
        "recurrence": "none", "priority": 3, "state": "active",
    })
    chart = client.request("POST", "/api/charts", {
        "title": "API示例：学习时长", "taskId": task_id, "metricId": duration_id, "days": 30,
    })
    points = client.request("GET", "/api/review/data?" + urlencode({
        "start": day, "end": day, "taskId": task_id, "metricId": duration_id,
    }))
    return {"taskId": task_id, "recordVersion": record["version"], "summary": summary,
            "scheduleId": schedule["scheduleId"], "chartId": chart["chartId"], "review": points}


def main():
    parser = argparse.ArgumentParser(description="创建示例任务、记录、日程和图表（会写入业务数据）")
    parser.add_argument("--base", default="http://127.0.0.1:8001", help="网站根地址，不包含/api")
    parser.add_argument("--username", required=True)
    parser.add_argument("--totp", action="store_true", help="使用已绑定验证器的验证码登录")
    args = parser.parse_args()
    client = ApiClient(args.base)
    if args.totp:
        client.login_totp(args.username, getpass.getpass("验证器6位验证码："))
    else:
        client.login(args.username, getpass.getpass("访问密码："))
    print(json.dumps(create_demo(client), ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
