"""
API 请求 / 响应 Pydantic 模型。

所有外部接口的 schema 集中在此定义，与业务逻辑解耦。
"""

from __future__ import annotations

from typing import List, Optional
from pydantic import BaseModel, Field


# ── 通用 ──────────────────────────────────────────────────────────────

class OkResponse(BaseModel):
    ok: bool = True
    id: Optional[str] = None
    message: str = ""


# ── 日历事件 ──────────────────────────────────────────────────────────

class EventOut(BaseModel):
    id: str
    summary: str
    start: str                    # ISO 8601
    end: str
    is_all_day: bool = False
    location: str = ""
    description: str = ""
    status: str = "confirmed"
    duration_minutes: int = 0
    provider: str = ""
    sync_state: str = ""


class ConflictOut(BaseModel):
    type: str                     # "conflict" | "tight"
    event_a: str                  # summary
    event_b: str
    time_a: str                   # "HH:MM–HH:MM"
    time_b: str
    overlap_minutes: int = 0
    gap_minutes: int = 0
    text: str                     # 格式化文字描述


class EventsResponse(BaseModel):
    date: str
    events: List[EventOut]
    conflicts: List[ConflictOut]
    provider: str = ""
    active_mode: str = ""


class EventCreateRequest(BaseModel):
    summary: str = Field(..., description="事件标题")
    date: str    = Field(..., description="日期 YYYY-MM-DD")
    start: str   = Field(..., description="开始时间 HH:MM")
    end: Optional[str]   = Field(None, description="结束时间 HH:MM（与 duration 二选一）")
    duration: int        = Field(60,   gt=0, description="持续分钟数（默认 60）")
    location: str        = Field("",   description="地点")
    description: str     = Field("",   description="备注")
    remind: int          = Field(0,    ge=0, description="提前提醒分钟数（0 = 不注册）")


class EventCreateResponse(BaseModel):
    ok: bool
    event_id: str = ""
    summary: str = ""
    start: str = ""
    end: str = ""
    reminder_registered: bool = False
    error: str = ""
    provider: str = ""
    sync_state: str = ""


class EventDeleteResponse(BaseModel):
    ok: bool
    event_id: str
    error: str = ""


# ── ROC 事件 ──────────────────────────────────────────────────────────

class RocEventOut(BaseModel):
    id: str
    name: str
    rule: str
    reminder_time: str
    lead_days: int
    description: str = ""
    # 计算字段（含年份时附带）
    event_date: Optional[str] = None
    reminder_date: Optional[str] = None


class RocListResponse(BaseModel):
    year: int
    events: List[RocEventOut]


class RocUpcomingItem(BaseModel):
    id: str
    name: str
    event_date: str
    reminder_date: str
    days_until_reminder: int
    days_until_event: int
    description: str = ""


class RocUpcomingResponse(BaseModel):
    today: str
    days: int
    upcoming: List[RocUpcomingItem]


class RocEventCreateRequest(BaseModel):
    id: str          = Field(..., description="唯一 ID（英文小写+下划线）")
    name: str        = Field(..., description="事件名称")
    rule: str        = Field(..., description="时间规则，如 每年6月15日")
    reminder_time: str = Field("09:00", description="推送时间 HH:MM")
    lead_days: int   = Field(7,  ge=0, description="提前提醒天数")
    description: str = Field("", description="说明")


class RocEventUpdateRequest(BaseModel):
    name: Optional[str] = None
    rule: Optional[str] = None
    reminder_time: Optional[str] = None
    lead_days: Optional[int] = None
    description: Optional[str] = None


# ── 提醒 ──────────────────────────────────────────────────────────────

class ReminderItem(BaseModel):
    summary: str
    start: str
    end: str
    lead_minutes: int
    trigger_at: str
    message: str


class RemindersResponse(BaseModel):
    window_minutes: int
    reminders: List[ReminderItem]
    provider: str = ""
    active_mode: str = ""


# ── Cron 任务 ─────────────────────────────────────────────────────────

class TaskItem(BaseModel):
    name: str
    description: str
    schedule_kind: str    # "at" | "cron"
    schedule_expr: str    # HH:MM 或 cron expr
    type: str             # "silent" | "report"


class TasksResponse(BaseModel):
    tasks: List[TaskItem]


class TaskSyncResponse(BaseModel):
    ok: bool = True
    dry_run: bool = False
    added: List[str] = []
    skipped: List[str] = []
    errors: List[str] = []
    message: str = ""


# ── 日报 ──────────────────────────────────────────────────────────────

class DailyPlanResponse(BaseModel):
    date: str
    events: List[EventOut]
    conflicts: List[ConflictOut]
    reminders_registered: int
    markdown: str         # 完整日报 Markdown 文本
    provider: str = ""


# ── Google 接入 ───────────────────────────────────────────────────────

class GoogleGuideStep(BaseModel):
    key: str
    title: str
    description: str


class GoogleSyncSummary(BaseModel):
    status: str = "idle"
    total: int = 0
    succeeded: int = 0
    failed: int = 0
    skipped: int = 0
    started_at: str = ""
    finished_at: str = ""
    last_error: str = ""


class GoogleStatusResponse(BaseModel):
    active_mode: str
    google_state: str
    has_token: bool
    masked_client_id: str = ""
    needs_initial_sync: bool = False
    current_step: str
    last_error: str = ""
    last_sync_time: str = ""
    last_sync_summary: GoogleSyncSummary


class GoogleGuideResponse(BaseModel):
    current_step: str
    active_mode: str
    google_state: str
    callback_url: str
    required_fields: List[str]
    steps: List[GoogleGuideStep]


class GoogleStartRequest(BaseModel):
    client_id: str = Field(..., description="Google OAuth Client ID")
    client_secret: str = Field(..., description="Google OAuth Client Secret")


class GoogleStartResponse(BaseModel):
    ok: bool = True
    authorize_url: str
    expires_at: str
    google_state: str


class GoogleSyncResponse(BaseModel):
    ok: bool = True
    active_mode: str
    google_state: str
    summary: GoogleSyncSummary
