import json
import uuid
from datetime import datetime

from pydantic import BaseModel, ConfigDict, Field, field_validator

# A view's state is the browser's own record of a list's settings — kept as
# sent, but bounded.
MAX_STATE_BYTES = 20_000


def _bounded(state: dict | None) -> dict | None:
    if state is not None and len(json.dumps(state)) > MAX_STATE_BYTES:
        raise ValueError("That view holds too much to save.")
    return state


class SavedViewCreate(BaseModel):
    page_id: uuid.UUID
    block_id: str = Field(min_length=1, max_length=100)
    name: str = Field(min_length=1, max_length=120)
    state: dict = {}
    is_default: bool = False

    @field_validator("state")
    @classmethod
    def _state_size(cls, v: dict) -> dict:
        return _bounded(v)


class SavedViewUpdate(BaseModel):
    name: str | None = Field(default=None, min_length=1, max_length=120)
    state: dict | None = None
    is_default: bool | None = None

    @field_validator("state")
    @classmethod
    def _state_size(cls, v: dict | None) -> dict | None:
        return _bounded(v)


class SavedViewRead(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: uuid.UUID
    page_id: uuid.UUID
    block_id: str
    name: str
    state: dict
    is_default: bool
    created_at: datetime
    updated_at: datetime
