from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional, Union

from ._clip import Clip
from ._transition import XFade, resolve_xfade


@dataclass
class _TrackEntry:
    """Internal bookkeeping for a clip placed on a track."""

    start: float
    clip: Clip
    xfade_name: str | None = None
    xfade_duration: float | None = None


class Track:
    """A timeline lane that holds clips.

    Mirrors VideoDB's ``Track`` — no explicit type.  The render engine
    infers the track's role (main video / overlay / audio / text) from the
    asset types of its clips.

    Clips are added with :meth:`add_clip` which takes ``(start, clip)``
    matching VideoDB's signature.
    """

    _entries: list[_TrackEntry]

    def __init__(self) -> None:
        self._entries = []

    def add_clip(
        self,
        start: float,
        clip: Clip,
        *,
        transition: Union[XFade, str, None] = None,
        transition_duration: Optional[float] = None,
    ) -> None:
        """Place *clip* on this track at *start* seconds.

        Args:
            start: Absolute position on the timeline (seconds).
            clip: A :class:`Clip` instance.
            transition: An xfade transition to apply between the previous
                clip and this one (only effective on the main video track).
            transition_duration: Cross-fade length in seconds.  Required
                when *transition* is set.
        """
        if start < 0:
            raise ValueError(f"start must be >= 0, got {start}")

        xfade_name: str | None = None
        xfade_dur: float | None = None

        if transition is not None:
            xfade_name = resolve_xfade(transition)
            if transition_duration is None:
                xfade_dur = 1.0
            else:
                if transition_duration <= 0:
                    raise ValueError(
                        f"transition_duration must be > 0, got {transition_duration}"
                    )
                xfade_dur = transition_duration
        elif transition_duration is not None:
            raise ValueError(
                "transition_duration requires a transition to be specified"
            )

        self._entries.append(
            _TrackEntry(
                start=start,
                clip=clip,
                xfade_name=xfade_name,
                xfade_duration=xfade_dur,
            )
        )

    @property
    def entries(self) -> list[_TrackEntry]:
        """Return entries sorted by start time."""
        return sorted(self._entries, key=lambda e: e.start)

    def __len__(self) -> int:
        return len(self._entries)

    def __repr__(self) -> str:
        return f"Track(clips={len(self._entries)})"
