from datetime import datetime from typing import Literal, Union, List, Tuple, Optional from pydantic import BaseModel, Field from uuid import UUID class Rect(BaseModel): x: float y: float width: float height: float class AnnotationBase(BaseModel): id: UUID page: int = Field(ge=0) type: str rect: Rect rotation: float = 0.0 z: int = 0 createdAt: datetime updatedAt: datetime class TextProps(BaseModel): text: str fontFamily: str = "Liberation Sans" fontSize: float = 14 color: str = "#000000" align: Literal["left", "center", "right"] = "left" bold: bool = False italic: bool = False lineHeight: float = 1.2 highlightColor: Optional[str] = None class TextAnnotation(AnnotationBase): type: Literal["text"] props: TextProps class DrawProps(BaseModel): paths: List[Tuple[float, float]] strokeColor: str = "#000000" strokeWidth: float = 2 opacity: float = 1.0 class DrawAnnotation(AnnotationBase): type: Literal["draw"] props: DrawProps class SignatureDrawProps(BaseModel): mode: Literal["draw"] ref: str strokeColor: str = "#000000" class SignatureTypeProps(BaseModel): mode: Literal["type"] text: str fontFamily: str color: str = "#000000" class SignatureAnnotation(AnnotationBase): type: Literal["signature"] props: Union[SignatureDrawProps, SignatureTypeProps] = Field(discriminator="mode") class ImageProps(BaseModel): ref: str naturalWidth: float naturalHeight: float class ImageAnnotation(AnnotationBase): type: Literal["image"] props: ImageProps class HighlightProps(BaseModel): color: str = "#FFEB3B" opacity: float = 0.3 class HighlightAnnotation(AnnotationBase): type: Literal["highlight"] props: HighlightProps class ShapeProps(BaseModel): kind: Literal["rect", "ellipse", "line", "arrow"] strokeColor: str = "#000000" fillColor: str = "transparent" strokeWidth: float = 2 class ShapeAnnotation(AnnotationBase): type: Literal["shape"] props: ShapeProps Annotation = Union[ TextAnnotation, DrawAnnotation, SignatureAnnotation, ImageAnnotation, HighlightAnnotation, ShapeAnnotation ] class AnnotationStateResponse(BaseModel): data: List[Annotation] updatedAt: datetime class AnnotationStateUpdateRequest(BaseModel): data: List[Annotation] baseUpdatedAt: datetime | None = None class AnnotationStateUpdateResponse(BaseModel): updatedAt: datetime