from enum import Enum
from typing import Any, Dict, Optional

from galtea.utils.case_insensitive_enum import CaseInsensitiveEnumMixin
from galtea.utils.from_camel_case_base_model import FromCamelCaseBaseModel


class SessionStatus(CaseInsensitiveEnumMixin, str, Enum):
    PENDING = "PENDING"
    COMPLETED = "COMPLETED"
    FAILED = "FAILED"


class SessionBase(FromCamelCaseBaseModel):
    """Base model for creating a new session."""

    custom_id: Optional[str] = (
        None  # client-provided ID to associate galtea session with the user's application session
    )
    version_id: Optional[str] = None
    test_case_id: Optional[str] = None
    context: Optional[str] = None  # flexible string context for user-defined information
    metadata: Optional[Dict[str, Any]] = None  # stores open fields from endpoint responses
    status: Optional[SessionStatus] = None


class Session(SessionBase):
    """Complete session model returned from the API."""

    id: str
    created_at: str
    deleted_at: Optional[str] = None
    stopping_reason: Optional[str] = None
    error: Optional[str] = None  # stores error message if session failed

    def is_test_based(self) -> bool:
        """Check if this session is test-based (has a test_case_id)."""
        return self.test_case_id is not None

    def is_monitoring(self) -> bool:
        """Check if this session is for production monitoring."""
        return self.test_case_id is None


class SessionUpdate(FromCamelCaseBaseModel):
    """Model for updating sessions with all optional fields (PATCH operation).

    Fields are Optional (defaulting to None) so they can be excluded from serialization
    if not set (via exclude_unset=True in the service).
    """

    id: Optional[str] = None
    created_at: Optional[str] = None
    deleted_at: Optional[str] = None
    stopping_reason: Optional[str] = None
    error: Optional[str] = None
    custom_id: Optional[str] = None
    version_id: Optional[str] = None
    test_case_id: Optional[str] = None
    context: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None
    status: Optional[SessionStatus] = None
