"""Versioning models for the ZenOTC SDK."""

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

from pydantic import BaseModel, Field


class AlgoVersionStatus(str, Enum):
    """Status of an algo version."""
    DRAFT = "draft"
    TESTING = "testing"
    PRODUCTION = "production"
    DEPRECATED = "deprecated"
    RETIRED = "retired"


class VersionEnvironment(str, Enum):
    """Environment for version deployment."""
    TEST = "test"
    PRODUCTION = "production"


class SDKVersionStatus(str, Enum):
    """Status of an SDK version."""
    CURRENT = "current"
    SUPPORTED = "supported"
    DEPRECATED = "deprecated"
    EOL = "eol"


class SDKPlatform(str, Enum):
    """SDK platform type."""
    PYTHON = "python"
    JAVASCRIPT = "javascript"
    TYPESCRIPT = "typescript"


class DeprecationType(str, Enum):
    """Type of deprecation."""
    ENDPOINT = "endpoint"
    FIELD = "field"
    ALGO = "algo"
    SDK_VERSION = "sdk_version"
    FEATURE = "feature"
    PARAMETER = "parameter"


class DeprecationStatus(str, Enum):
    """Status of a deprecation."""
    ANNOUNCED = "announced"
    WARNING = "warning"
    SUNSET = "sunset"
    COMPLETE = "complete"
    CANCELLED = "cancelled"


class Environment(str, Enum):
    """Environment type."""
    TEST = "test"
    STAGING = "staging"
    PRODUCTION = "production"


# ==================== Algo Versions ====================

class AlgoVersionConfig(BaseModel):
    """Configuration for an algo version."""
    parameters: dict[str, Any] = Field(default_factory=dict)
    defaults: dict[str, Any] = Field(default_factory=dict)
    validations: dict[str, list[Any]] = Field(default_factory=dict)


class AlgoVersion(BaseModel):
    """Algo version details."""
    version_id: str = Field(alias="versionId")
    algo_type: str = Field(alias="algoType")
    version: str
    status: AlgoVersionStatus
    environment: VersionEnvironment
    description: Optional[str] = None
    changelog: Optional[str] = None
    config: Optional[AlgoVersionConfig] = None
    published_at: Optional[datetime] = Field(None, alias="publishedAt")
    deprecated_at: Optional[datetime] = Field(None, alias="deprecatedAt")
    retired_at: Optional[datetime] = Field(None, alias="retiredAt")
    created_at: Optional[datetime] = Field(None, alias="createdAt")
    updated_at: Optional[datetime] = Field(None, alias="updatedAt")

    class Config:
        populate_by_name = True


class AlgoVersionSummary(BaseModel):
    """Summary of an algo version."""
    version: str
    version_id: str = Field(alias="versionId")
    status: AlgoVersionStatus
    changelog: Optional[str] = None
    published_at: Optional[datetime] = Field(None, alias="publishedAt")
    description: Optional[str] = None

    class Config:
        populate_by_name = True


class AlgoTypeSummary(BaseModel):
    """Summary of an algo type."""
    algo_type: str = Field(alias="algoType")
    current_version: Optional[str] = Field(None, alias="currentVersion")
    current_version_id: Optional[str] = Field(None, alias="currentVersionId")

    class Config:
        populate_by_name = True


# ==================== SDK Versions ====================

class SDKVersion(BaseModel):
    """SDK version details."""
    sdk_version_id: str = Field(alias="sdkVersionId")
    sdk_version: str = Field(alias="sdkVersion")
    platform: SDKPlatform
    status: SDKVersionStatus
    min_backend_version: str = Field(alias="minBackendVersion")
    max_backend_version: Optional[str] = Field(None, alias="maxBackendVersion")
    release_notes: Optional[str] = Field(None, alias="releaseNotes")
    release_date: Optional[datetime] = Field(None, alias="releaseDate")
    download_url: Optional[str] = Field(None, alias="downloadUrl")
    documentation_url: Optional[str] = Field(None, alias="documentationUrl")
    breaking_changes: list[str] = Field(default_factory=list, alias="breakingChanges")
    new_features: list[str] = Field(default_factory=list, alias="newFeatures")
    deprecations: list[str] = Field(default_factory=list)
    bug_fixes: list[str] = Field(default_factory=list, alias="bugFixes")
    migration_guide: Optional[str] = Field(None, alias="migrationGuide")
    deprecated_at: Optional[datetime] = Field(None, alias="deprecatedAt")
    eol_date: Optional[datetime] = Field(None, alias="eolDate")

    class Config:
        populate_by_name = True


class SDKVersionSummary(BaseModel):
    """Summary of an SDK version."""
    sdk_version: str = Field(alias="sdkVersion")
    sdk_version_id: str = Field(alias="sdkVersionId")
    status: SDKVersionStatus
    release_date: Optional[datetime] = Field(None, alias="releaseDate")
    eol_date: Optional[datetime] = Field(None, alias="eolDate")
    download_url: Optional[str] = Field(None, alias="downloadUrl")
    documentation_url: Optional[str] = Field(None, alias="documentationUrl")

    class Config:
        populate_by_name = True


class CurrentSDKVersion(BaseModel):
    """Current SDK version for a platform."""
    platform: SDKPlatform
    available: bool = True
    sdk_version: Optional[str] = Field(None, alias="sdkVersion")
    sdk_version_id: Optional[str] = Field(None, alias="sdkVersionId")
    download_url: Optional[str] = Field(None, alias="downloadUrl")
    documentation_url: Optional[str] = Field(None, alias="documentationUrl")
    release_date: Optional[datetime] = Field(None, alias="releaseDate")
    release_notes: Optional[str] = Field(None, alias="releaseNotes")
    new_features: list[str] = Field(default_factory=list, alias="newFeatures")

    class Config:
        populate_by_name = True


class SDKSupportStatus(BaseModel):
    """SDK version support status."""
    supported: bool
    status: Optional[SDKVersionStatus] = None
    eol_date: Optional[datetime] = Field(None, alias="eolDate")
    upgrade_recommendation: Optional[str] = Field(None, alias="upgradeRecommendation")

    class Config:
        populate_by_name = True


# ==================== Deprecations ====================

class DeprecationWarning(BaseModel):
    """Deprecation warning message."""
    deprecation_id: str = Field(alias="deprecationId")
    type: DeprecationType
    identifier: str
    message: str
    sunset_date: datetime = Field(alias="sunsetDate")
    replacement_path: Optional[str] = Field(None, alias="replacementPath")
    migration_docs: Optional[str] = Field(None, alias="migrationDocs")

    class Config:
        populate_by_name = True


class Deprecation(BaseModel):
    """Full deprecation details."""
    deprecation_id: str = Field(alias="deprecationId")
    type: DeprecationType
    identifier: str
    name: Optional[str] = None
    description: Optional[str] = None
    status: DeprecationStatus
    announced_at: datetime = Field(alias="announcedAt")
    warning_start_date: datetime = Field(alias="warningStartDate")
    sunset_date: datetime = Field(alias="sunsetDate")
    replacement_path: Optional[str] = Field(None, alias="replacementPath")
    replacement_description: Optional[str] = Field(None, alias="replacementDescription")
    migration_docs: Optional[str] = Field(None, alias="migrationDocs")
    migration_steps: list[str] = Field(default_factory=list, alias="migrationSteps")
    usage_count: int = Field(0, alias="usageCount")
    last_used_at: Optional[datetime] = Field(None, alias="lastUsedAt")
    created_at: Optional[datetime] = Field(None, alias="createdAt")
    updated_at: Optional[datetime] = Field(None, alias="updatedAt")

    class Config:
        populate_by_name = True


# ==================== Version Resolution ====================

class VersionResolution(BaseModel):
    """Resolved version for algo execution."""
    algo_type: str = Field(alias="algoType")
    version: str
    version_id: str = Field(alias="versionId")
    sdk_compatible: bool = Field(alias="sdkCompatible")
    environment: Environment
    deprecation_warnings: list[DeprecationWarning] = Field(
        default_factory=list, alias="deprecationWarnings"
    )
    config: Optional[AlgoVersionConfig] = None

    class Config:
        populate_by_name = True


class CompatibilityCheck(BaseModel):
    """Compatibility check result."""
    compatible: bool
    issues: list[str] = Field(default_factory=list)
    warnings: list[str] = Field(default_factory=list)

    class Config:
        populate_by_name = True


# ==================== Environment ====================

class MaintenanceStatus(BaseModel):
    """Environment maintenance status."""
    in_maintenance: bool = Field(alias="inMaintenance")
    message: Optional[str] = None
    ends_at: Optional[datetime] = Field(None, alias="endsAt")

    class Config:
        populate_by_name = True


class EnvironmentInfo(BaseModel):
    """Environment information."""
    environment: Environment
    configured: bool = True
    display_name: Optional[str] = Field(None, alias="displayName")
    is_active: bool = Field(True, alias="isActive")
    maintenance: Optional[MaintenanceStatus] = None
    enabled_algos: list[str] = Field(default_factory=list, alias="enabledAlgos")
    feature_flags: dict[str, Any] = Field(default_factory=dict, alias="featureFlags")

    class Config:
        populate_by_name = True
