"""Export job models."""

from __future__ import annotations

from datetime import datetime
from enum import Enum

from pydantic import Field

from ticksupply.models.catalog import DatastreamInfo
from ticksupply.models.common import BaseAPIModel


class ExportStatus(str, Enum):
    """Status of an export job."""

    QUEUED = "queued"
    RUNNING = "running"
    SUCCEEDED = "succeeded"
    FAILED = "failed"
    CANCELED = "canceled"


class ExportJob(BaseAPIModel):
    """An export job.

    Attributes:
        id: Unique job ID (prefixed format, e.g., exp_xxx).
        datastream_id: Datastream being exported.
        start_time: Start of data range (nanoseconds since Unix epoch).
        end_time: End of data range (nanoseconds since Unix epoch).
        format: Export file format (e.g., "csv").
        status: Current job status.
        reason: Failure reason (only present when status is "failed").
        created_at: When the job was created.
        started_at: When processing started (if started).
        finished_at: When the job finished (if completed).
    """

    id: str
    datastream_id: int
    start_time: int
    end_time: int
    format: str
    status: ExportStatus
    reason: str | None = None
    created_at: datetime
    started_at: datetime | None = None
    finished_at: datetime | None = None


class PaginatedExportJobs(BaseAPIModel):
    """Paginated list of export jobs."""

    items: list[ExportJob]
    total: int
    limit: int
    next_page_token: str | None = None

    @property
    def has_next(self) -> bool:
        """Check if there are more pages."""
        return self.next_page_token is not None


class ArtifactDownload(BaseAPIModel):
    """A downloadable artifact with presigned URL.

    Attributes:
        id: Artifact ID (prefixed format, e.g., art_xxx).
        url: Pre-signed S3 URL (valid for 5 minutes).
        bytes: File size in bytes.
        filename: Suggested filename for download.
    """

    id: str
    url: str
    bytes: int
    filename: str


class ExportDownloadResponse(BaseAPIModel):
    """Download response with multiple artifacts.

    Large exports may be split into multiple files (e.g., hourly or daily
    partitions). This response contains presigned URLs for all artifacts.

    Attributes:
        artifacts: List of downloadable artifacts with presigned URLs.
        count: Number of artifacts.
        total_bytes: Total size across all artifacts in bytes.
    """

    artifacts: list[ArtifactDownload]
    count: int
    total_bytes: int

    @property
    def is_single_file(self) -> bool:
        """Check if export produced a single file."""
        return self.count == 1

    @property
    def url(self) -> str | None:
        """Get URL for single-file exports (convenience property).

        Returns:
            The download URL if this is a single-file export, None otherwise.
        """
        if self.is_single_file:
            return self.artifacts[0].url
        return None


class AvailabilityRange(BaseAPIModel):
    """A time range with available data.

    Attributes:
        from_ns: Start of range (nanoseconds since Unix epoch).
        to_ns: End of range (nanoseconds since Unix epoch).
        rows_estimate: Estimated number of rows in this range.
    """

    from_ns: int = Field(alias="from")
    to_ns: int = Field(alias="to")
    rows_estimate: int


class AvailabilityResponse(BaseAPIModel):
    """Response for data availability query.

    Attributes:
        datastream: Datastream information.
        ranges: Time ranges with available data.
        updated_at: When availability data was last updated.
    """

    datastream: DatastreamInfo
    ranges: list[AvailabilityRange]
    updated_at: datetime
