"""Pydantic v2 data models for the bitable subsystem.

All models use ``model_config = ConfigDict(...)`` per project convention.
Field configs are stored as JSONB in PostgreSQL; the Pydantic models here
define the application-layer shape.
"""

from __future__ import annotations

from datetime import datetime, timezone
from enum import Enum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field as PydanticField


def _utcnow() -> datetime:
    return datetime.now(timezone.utc)


class FieldType(str, Enum):
    """Supported field types in bitable tables."""

    text = "text"
    number = "number"
    date = "date"
    select = "select"
    multiselect = "multiselect"
    attachment = "attachment"
    image = "image"
    formula = "formula"
    lookup = "lookup"


class FieldOwner(str, Enum):
    """Who owns a field's data — determines upsert merge behavior."""

    agent = "agent"
    user = "user"


class ViewType(str, Enum):
    """Supported view types (v1: grid only)."""

    grid = "grid"
    kanban = "kanban"
    gantt = "gantt"
    gallery = "gallery"
    form = "form"


class RecalcStatus(str, Enum):
    """Status of an asynchronous formula recalculation task."""

    pending = "pending"
    calculating = "calculating"
    done = "done"
    error = "error"


class BitableFile(BaseModel):
    """Top-level container grouping related tables (多维表格文件).

    Owns metadata (name/icon/description/owner). Tables reference their
    parent file via ``file_id``. The file is the unit of ownership sharing
    and the top of the ``文件 → 数据表 → 字段/记录`` navigation hierarchy.
    """

    model_config = ConfigDict(from_attributes=True)

    id: str
    name: str
    icon: str = "📋"
    description: str = ""
    owner_user_id: str | None = None
    created_at: datetime = PydanticField(default_factory=_utcnow)
    updated_at: datetime = PydanticField(default_factory=_utcnow)


class Table(BaseModel):
    """A bitable table — collection of fields and records."""

    model_config = ConfigDict(from_attributes=True)

    id: str
    file_id: str | None = None
    name: str
    description: str = ""
    primary_key_field_id: str | None = None
    owner_user_id: str | None = None
    created_at: datetime = PydanticField(default_factory=_utcnow)
    updated_at: datetime = PydanticField(default_factory=_utcnow)


# ---------------------------------------------------------------------------
# Default field templates (R2)
# ---------------------------------------------------------------------------

# Status select field options — labels and colors match Feishu Bitable defaults.
_STATUS_OPTIONS: list[dict[str, Any]] = [
    {"label": "未开始", "value": "not_started", "color": "default"},
    {"label": "进行中", "value": "in_progress", "color": "processing"},
    {"label": "已完成", "value": "done", "color": "success"},
]

#: Templates for the 5 default fields created on every new table (R2).
#: agent-owned fields (创建人/创建时间) are auto-filled by the service layer
#: on record creation; user-owned fields are user-editable.
DEFAULT_FIELD_TEMPLATES: list[dict[str, Any]] = [
    {
        "name": "标题",
        "field_type": FieldType.text,
        "owner": FieldOwner.user,
        "config": {},
    },
    {
        "name": "状态",
        "field_type": FieldType.select,
        "owner": FieldOwner.user,
        "config": {"options": _STATUS_OPTIONS},
    },
    {
        "name": "日期",
        "field_type": FieldType.date,
        "owner": FieldOwner.user,
        "config": {},
    },
    {
        "name": "创建人",
        "field_type": FieldType.text,
        "owner": FieldOwner.agent,
        "config": {},
    },
    {
        "name": "创建时间",
        "field_type": FieldType.date,
        "owner": FieldOwner.agent,
        "config": {},
    },
]


class Field(BaseModel):
    """A column definition in a bitable table.

    ``config`` varies by ``field_type``:
    - select/multiselect: ``{"options": [{"label": "...", "value": "..."}]}``
    - formula: ``{"formula_expr": "=SUM({field_abc})"}``
    - lookup: ``{"lookup_target": {"table_id": "...", "field_id": "...", "filter_field_id": "...", "filter_value": "..."}}``
    """

    model_config = ConfigDict(from_attributes=True)

    id: str
    table_id: str
    name: str
    field_type: FieldType
    config: dict[str, Any] = PydanticField(default_factory=dict)
    owner: FieldOwner = FieldOwner.user
    created_at: datetime = PydanticField(default_factory=_utcnow)


class Record(BaseModel):
    """A row in a bitable table. ``values`` maps field_id → value."""

    model_config = ConfigDict(from_attributes=True)

    id: str
    table_id: str
    values: dict[str, Any] = PydanticField(default_factory=dict)
    created_at: datetime = PydanticField(default_factory=_utcnow)
    updated_at: datetime = PydanticField(default_factory=_utcnow)


class View(BaseModel):
    """A saved view of a table (filters, sorts, hidden fields)."""

    model_config = ConfigDict(from_attributes=True)

    id: str
    table_id: str
    name: str
    view_type: ViewType = ViewType.grid
    config: dict[str, Any] = PydanticField(default_factory=dict)
    created_at: datetime = PydanticField(default_factory=_utcnow)


class RecalcTask(BaseModel):
    """An asynchronous formula recalculation task."""

    model_config = ConfigDict(from_attributes=True)

    id: str
    table_id: str
    record_id: str
    field_id: str
    status: RecalcStatus = RecalcStatus.pending
    error_message: str | None = None
    queued_at: datetime = PydanticField(default_factory=_utcnow)
    completed_at: datetime | None = None
