"""
Database Models for Download Management

Contains ORM models for tracking resource download status and retry logic.
"""

from datetime import UTC, datetime
from enum import Enum
from functools import partial
from typing import Optional

from sqlalchemy import DateTime, Integer, String, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Base(DeclarativeBase):
    pass


class FailureType(str, Enum):
    """Enum for failure types - ensures consistency across the codebase"""

    NOT_FOUND = "not_found"
    FORBIDDEN = "forbidden"
    GONE = "gone"
    RATE_LIMITED = "rate_limited"
    SERVER_ERROR = "server_error"
    RECAPTCHA_PROTECTION = "recaptcha_protection"
    INCOMPATIBLE_FORMAT = "incompatible_format"
    TIMEOUT = "timeout"
    NETWORK_ERROR = "network_error"
    UNKNOWN_ERROR = "unknown_error"


class DownloadStatus(str, Enum):
    """Status values for resource download tracking."""

    AVAILABLE = "available"
    TEMPORARILY_FAILED = "temporarily_failed"
    PERMANENTLY_FAILED = "permanently_failed"


class ResourceDownloadStatus(Base):
    """Database model for tracking resource download status"""

    __tablename__ = "resource_download_status"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    resource_id: Mapped[int] = mapped_column(
        Integer, unique=True, nullable=False, index=True
    )

    # Status tracking
    status: Mapped[str] = mapped_column(
        String(50), nullable=False, default="available"
    )  # available, temporarily_failed, permanently_failed
    failure_type: Mapped[Optional[str]] = mapped_column(
        String(100), nullable=True
    )  # not_found, rate_limited, timeout, etc.
    failure_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    # Retry timing
    retry_after_timestamp: Mapped[Optional[datetime]] = mapped_column(
        DateTime, nullable=True
    )  # When this can be retried (NULL = permanent)
    last_attempt_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime, nullable=True
    )
    permanent_failure_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime, nullable=True
    )  # When permanently failed

    # Statistics
    total_retry_count: Mapped[int] = mapped_column(Integer, default=0)
    today_retry_count: Mapped[int] = mapped_column(Integer, default=0)

    # Timestamps
    created_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime, default=partial(datetime.now, UTC)
    )
    updated_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        default=partial(datetime.now, UTC),
        onupdate=partial(datetime.now, UTC),
    )

    def __repr__(self) -> str:
        return f"<ResourceDownloadStatus(resource_id={self.resource_id}, status='{self.status}', failure_type='{self.failure_type}')>"
