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


class CvatApiAttribute(BaseModel):
    """Represents an attribute in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    spec_id: int
    value: str


class CvatApiTag(BaseModel):
    """Represents a tag in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    id: int
    label_id: int
    color: str
    frame: int
    group: int
    source: str  # e.g., "manual"
    attributes: List[CvatApiAttribute]


class CvatApiShape(BaseModel):
    """Represents a shape in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    id: int
    label_id: int
    type: str
    frame: int
    group: int
    source: str  # e.g., "manual"
    occluded: bool
    outside: bool
    label_name: str
    z_order: int
    rotation: float
    points: List[float]
    attributes: List[CvatApiAttribute]
    elements: List[Any]


class CvatApiJobAnnotations(BaseModel):
    """Represents job annotations in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    version: int
    tags: List[CvatApiTag]
    shapes: List[CvatApiShape]
    tracks: List[Any]


class CvatApiAttributeDefinition(BaseModel):
    """Represents an attribute definition in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    id: int
    name: str
    mutable: bool
    input_type: str
    default_value: str
    values: List[str]  # Possible values for the attribute


class CvatApiLabelDefinition(BaseModel):
    """Represents a label definition in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    id: int
    name: str
    color: str
    attributes: List[CvatApiAttributeDefinition]
    type: str
    svg: str
    sublabels: List["CvatApiLabelDefinition"]  # Recursive type for nested labels
    project_id: int
    task_id: int
    parent_id: Optional[int] = None  # ID of the parent label, if any
    has_parent: bool  # Indicates if this label has a parent label


class CvatApiMetainformationFrame(BaseModel):
    """Represents a frame in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    width: int
    height: int
    name: str
    related_files: bool
    has_related_context: bool


class CvatApiJobMediasMetainformation(BaseModel):
    """Represents the metainformation for a job in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    chunks_updated_date: str
    chunk_size: int
    size: int
    image_quality: int
    start_frame: int
    stop_frame: int
    frame_filter: str
    frames: List[CvatApiMetainformationFrame]
    deleted_frames: List[int]
    included_frames: Optional[List[int]] = None


class CvatApiTaskMediasMetainformation(BaseModel):
    """Represents the metainformation for a task in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    chunks_updated_date: str
    chunk_size: int
    size: int
    image_quality: int
    start_frame: int
    stop_frame: int
    frame_filter: str
    frames: List[CvatApiMetainformationFrame]
    deleted_frames: List[int]
    included_frames: Optional[List[int]] = None


class CvatApiJobDetails(BaseModel):
    """Represents job details in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    url: str
    id: int
    task_id: int
    project_id: int
    assignee_id: Optional[int] = None
    assignee: Optional[str] = None
    status: str
    stage: str
    state: str
    mode: str
    dimension: str
    start_frame: int
    stop_frame: int
    data_chunk_size: int
    data_compressed_chunk_size: int
    data_original_chunk_size: int
    created_date: str
    updated_date: str
    issue_tracker: Optional[str] = None
    labels: List[CvatApiLabelDefinition]


class CvatApiTaskDetails(BaseModel):
    """Represents task details in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    url: str
    id: int
    name: str
    project_id: int
    mode: str
    owner: str
    assignee: Optional[str] = None
    bug_tracker: Optional[str] = None
    created_date: str
    updated_date: str
    overlap: int
    segment_size: int
    status: str
    labels: List[CvatApiLabelDefinition]
    segments: List[CvatApiJobDetails]
    data_chunk_size: int
    data_compressed_chunk_size: int
    data_original_chunk_size: int
    size: int
    image_quality: int
    data: int
    dimension: str
    subset: str
    organization: Optional[int] = None
    target_storage: Optional[dict] = None
    source_storage: Optional[dict] = None


class CvatApiTaskAnnotations(BaseModel):
    """Represents annotations for a task in CVAT API."""
    
    model_config = ConfigDict(extra='forbid')
    
    version: int
    tags: List[CvatApiTag]
    shapes: List[CvatApiShape]
    tracks: List[Any]
