"""Models for Archer record operations."""

from typing import Dict, List, Optional, Any, Union
from enum import IntEnum
from pydantic import BaseModel, Field, field_validator, ConfigDict


class FieldType(IntEnum):
    """
    Archer field types based on API documentation.
    Reference: Metadata Field documentation
    """
    TEXT = 1
    NUMERIC = 2
    DATE = 3
    VALUES_LIST = 4
    TRACKING_ID = 6
    EXTERNAL_LINKS = 7
    USERS_GROUPS_LIST = 8
    CROSS_REFERENCE = 9
    ATTACHMENT = 11
    IMAGE = 12
    CAST_SCORECARD = 14
    MATRIX = 16
    IP_ADDRESS = 19
    RECORD_STATUS = 20
    FIRST_PUBLISHED = 21
    LAST_UPDATED_FIELD = 22
    RELATED_RECORDS = 23
    SUB_FORM = 24
    HISTORY_LOG = 25
    MULTIPLE_REFERENCE_DISPLAY_CONTROL = 27
    QUESTIONNAIRE_REFERENCE = 28
    ACCESS_HISTORY = 29
    VOTING = 30
    SCHEDULER = 31
    CAST_FIELD_VALUE = 1001


class FieldContent(BaseModel):
    """Represents a single field's content in an Archer record."""
    
    model_config = ConfigDict(extra='allow', use_enum_values=True)
    
    Type: int = Field(..., description="Field type ID from FieldType enum")
    Value: Union[str, int, float, List, Dict, None] = Field(..., description="Field value")
    FieldId: Optional[int] = Field(None, description="Field ID")
    
    @field_validator('Type')
    @classmethod
    def validate_type(cls, v):
        """Ensure Type is a valid FieldType."""
        valid_types = [ft.value for ft in FieldType]
        if v not in valid_types:
            # Log warning but don't fail - allow unknown types
            import logging
            logger = logging.getLogger(__name__)
            logger.warning(f"Unknown field type: {v}. Proceeding anyway.")
        return v


class RecordContent(BaseModel):
    """Represents the content structure of an Archer record."""
    
    model_config = ConfigDict(extra='allow')
    
    Id: Optional[int] = Field(None, description="Content/Record ID")
    LevelId: int = Field(..., description="Application ID")
    FieldContents: Dict[str, FieldContent] = Field(
        default_factory=dict,
        description="Dictionary of field contents keyed by field ID or name"
    )
    Version: Optional[str] = Field(None, description="Record version for optimistic locking")


class RecordCreateRequest(BaseModel):
    """Request model for creating a new record."""
    
    model_config = ConfigDict(extra='allow')
    
    Content: RecordContent
    SubformFieldId: Optional[int] = Field(None, description="Required when saving subform content")
    
    @classmethod
    def from_fields(
        cls,
        application_id: int,
        field_values: Dict[str, Any],
        subform_field_id: Optional[int] = None
    ) -> "RecordCreateRequest":
        """Convenient factory method to create a request from simple field values."""
        field_contents = {}
        for field_name, value in field_values.items():
            # Infer field type from value
            if isinstance(value, str):
                field_type = FieldType.TEXT
            elif isinstance(value, (int, float)):
                field_type = FieldType.NUMERIC
            elif isinstance(value, list):
                field_type = FieldType.VALUES_LIST
            else:
                field_type = FieldType.TEXT
            
            field_contents[field_name] = FieldContent(
                Type=field_type,
                Value=value
            )
        
        content = RecordContent(
            LevelId=application_id,
            FieldContents=field_contents
        )
        
        return cls(Content=content, SubformFieldId=subform_field_id)


class RecordUpdateRequest(BaseModel):
    """Request model for updating an existing record."""
    
    model_config = ConfigDict(extra='allow')
    
    Content: RecordContent
    SubformFieldId: Optional[int] = Field(None, description="Required when saving subform content")
    
    @field_validator('Content')
    @classmethod
    def validate_content_has_id(cls, v):
        """Ensure Content has an Id for updates."""
        if v.Id is None:
            raise ValueError("Content.Id is required for update operations")
        return v


class RecordResponse(BaseModel):
    """Response model from record operations."""
    
    model_config = ConfigDict(extra='allow')
    
    Links: List[Any] = Field(default_factory=list)
    RequestedObject: Dict[str, Any] = Field(default_factory=dict)
    IsSuccessful: bool
    ValidationMessages: List[str] = Field(default_factory=list)
    
    @property
    def record_id(self) -> Optional[int]:
        """Extract the record ID from the response."""
        return self.RequestedObject.get("Id")
    
    @property
    def has_errors(self) -> bool:
        """Check if the response contains errors."""
        return not self.IsSuccessful or len(self.ValidationMessages) > 0