"""CointimeSeries model — a time series of cointime data for plotting."""

import datetime
from typing import Iterator, List, Optional

from pydantic import BaseModel

from boxtime.models.cointime.cointime_data_point import CointimeDataPoint


class CointimeSeries(BaseModel):
    """A time series of cointime data optimized for plotting.

    Returned by ``get_coinblocks_*`` and ``get_total_coinblocks_*`` methods
    on :class:`~boxtime.clients.cointime_client.Cointime`.
    """

    heights: List[int]
    """Block heights."""

    timestamps: List[int]
    """Block timestamps in milliseconds."""

    values: List[int]
    """Cointime values in nanoERG-blocks (CBC, CBD, CBS, TCBC, TCBD, or TCBS)."""

    prices: Optional[List[float]] = None
    """ERG/USD prices for each data point.
    
    None if prices were not requested (with_price=False) or if any price
    is missing from the erg_prices table (incomplete data).
    """

    def __iter__(self) -> Iterator[CointimeDataPoint]:
        """Iterate over the series as CointimeDataPoint objects."""
        prices = self.prices if self.prices is not None else [None] * len(self)
        for height, timestamp, value, price in zip(
            self.heights, self.timestamps, self.values, prices
        ):
            yield CointimeDataPoint(
                height=height,
                timestamp=timestamp,
                value=value,
                price=price,
            )

    def __len__(self) -> int:
        """Return the number of data points in the series."""
        return len(self.heights)

    @property
    def dates(self) -> List[datetime.date]:
        """Convert timestamps to dates for plotting."""
        return [
            datetime.datetime.fromtimestamp(
                ts / 1000, tz=datetime.timezone.utc
            ).date()
            for ts in self.timestamps
        ]
