"""Models for Archer applications and field definitions."""

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


class FieldTypeEnum(IntEnum):
    """
    Field types in Archer based on official 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  # Cross-Application Status Tracking
    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  # Content Access History
    VOTING = 30
    SCHEDULER = 31
    CAST_FIELD_VALUE = 1001  # Cross-Application Status Tracking Field Value


class FieldDefinition(BaseModel):
    """Represents a field definition in an Archer application."""
    
    model_config = ConfigDict(extra='allow')  # Allow extra fields from API
    
    Id: int = Field(..., description="Field ID")
    Name: str = Field(..., description="Field name")
    Type: int = Field(..., description="Field type")
    LevelId: int = Field(..., description="Application/Level ID")
    IsRequired: Optional[bool] = Field(None, description="Whether field is required")
    
    @property
    def type_name(self) -> str:
        """Get human-readable field type name."""
        try:
            return FieldTypeEnum(self.Type).name
        except ValueError:
            return f"Unknown({self.Type})"
    
    @property
    def type_syntax(self) -> str:
        """Get the field type syntax string."""
        type_syntax_map = {
            1: "FieldType.Text",
            2: "FieldType.Numeric",
            3: "FieldType.Date",
            4: "FieldType.ValuesList",
            6: "FieldType.TrackingID",
            7: "FieldType.ExternalLinks",
            8: "FieldType.UsersGroupsList",
            9: "FieldType.CrossReference",
            11: "FieldType.Attachment",
            12: "FieldType.Image",
            14: "FieldType.CastScoreCard",
            16: "FieldType.Matrix",
            19: "FieldType.IpAddress",
            20: "FieldType.RecordStatus",
            21: "FieldType.FirstPublishedDate",
            22: "FieldType.LastUpdatedField",
            23: "FieldType.RelatedRecords",
            24: "FieldType.SubForm",
            25: "FieldType.HistoryLog",
            27: "FieldType.MultipleReferenceDisplayControl",
            28: "FieldType.QuestionnaireReference",
            29: "FieldType.ContentAccessHistory",
            30: "FieldType.Voting",
            31: "FieldType.Scheduler",
            1001: "FieldType.CrossApplicationStatusTrackingFieldValue",
        }
        return type_syntax_map.get(self.Type, f"Unknown({self.Type})")


class Application(BaseModel):
    """Represents an Archer application."""
    
    model_config = ConfigDict(extra='allow')  # Allow extra fields from API
    
    Id: int = Field(..., description="Application ID")
    Name: str = Field(..., description="Application name")
    Alias: Optional[str] = Field(None, description="Application alias")
    Type: Optional[int] = Field(None, description="Application type")
    LanguageId: Optional[int] = Field(None)
    
    # Additional metadata
    fields: Optional[List[FieldDefinition]] = Field(None, description="Application fields")
    
    def get_field_by_name(self, field_name: str) -> Optional[FieldDefinition]:
        """Get field definition by name."""
        if not self.fields:
            return None
        return next((f for f in self.fields if f.Name == field_name), None)
    
    def get_field_by_id(self, field_id: int) -> Optional[FieldDefinition]:
        """Get field definition by ID."""
        if not self.fields:
            return None
        return next((f for f in self.fields if f.Id == field_id), None)