"""Tests for the DecoderRepository module."""

from __future__ import annotations

from pathlib import Path

from sqlalchemy.orm import Session

from conftest import init_test_db
from database.repositories import (
    DecoderRepository,
    ProjectRepository,
    TrackRepository,
)


def _create_track(
    session: Session,
    project_id: str,
    relative_path: str = "song.wav",
    sha256: str = "abc123",
) -> object:
    """Create and persist a track for testing.

    Args:
        session: An active SQLAlchemy session.
        project_id: UUID of the parent project.
        relative_path: Relative path for the track.
        sha256: SHA-256 hash.

    Returns:
        The created :class:`Track` instance.
    """
    return TrackRepository.create_track(
        session,
        project_id=project_id,
        relative_path=relative_path,
        original_filename=relative_path.split("/")[-1],
        sha256=sha256,
        file_size=1024,
    )


def test_update_metadata(tmp_path: Path) -> None:
    """Verify that metadata is stored on the track."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)
        track = _create_track(session, project.id)

        DecoderRepository.update_metadata(
            session,
            track,
            duration=120.5,
            sample_rate=44100,
            channels=2,
            bit_depth=16,
        )

        assert track.duration == 120.5
        assert track.sample_rate == 44100
        assert track.channels == 2
        assert track.bit_depth == 16
    finally:
        session.close()


def test_update_metadata_bit_depth_none(tmp_path: Path) -> None:
    """Verify that bit_depth can be set to None."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)
        track = _create_track(session, project.id)

        DecoderRepository.update_metadata(
            session,
            track,
            duration=60.0,
            sample_rate=48000,
            channels=1,
            bit_depth=None,
        )

        assert track.bit_depth is None
        assert track.duration == 60.0
    finally:
        session.close()


def test_update_metadata_does_not_modify_immutable_fields(
    tmp_path: Path,
) -> None:
    """Verify that SHA-256, path, and filename are not modified."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)
        track = _create_track(
            session, project.id, relative_path="album/song.wav", sha256="original_hash"
        )

        original_path = track.relative_path
        original_filename = track.original_filename
        original_sha256 = track.sha256

        DecoderRepository.update_metadata(
            session,
            track,
            duration=30.0,
            sample_rate=22050,
            channels=1,
            bit_depth=24,
        )

        assert track.relative_path == original_path
        assert track.original_filename == original_filename
        assert track.sha256 == original_sha256
    finally:
        session.close()


def test_list_tracks_without_metadata(tmp_path: Path) -> None:
    """Verify that only tracks without metadata are returned."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)
        _create_track(session, project.id, "no_meta.wav", "h1")
        track_with = _create_track(session, project.id, "has_meta.wav", "h2")

        DecoderRepository.update_metadata(
            session,
            track_with,
            duration=10.0,
            sample_rate=44100,
            channels=1,
            bit_depth=16,
        )

        tracks = DecoderRepository.list_tracks_without_metadata(session, project.id)

        assert len(tracks) == 1
        assert tracks[0].relative_path == "no_meta.wav"
    finally:
        session.close()


def test_list_tracks_without_metadata_excludes_missing(
    tmp_path: Path,
) -> None:
    """Verify that MISSING tracks are excluded from the list."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)
        track = _create_track(session, project.id, "missing.wav", "h1")
        TrackRepository.mark_as_missing(session, track)

        tracks = DecoderRepository.list_tracks_without_metadata(session, project.id)

        assert len(tracks) == 0
    finally:
        session.close()


def test_list_tracks_without_metadata_empty(tmp_path: Path) -> None:
    """Verify that an empty list is returned when no tracks exist."""
    session = init_test_db(tmp_path)
    try:
        project = ProjectRepository.get_default_project(session)

        tracks = DecoderRepository.list_tracks_without_metadata(session, project.id)

        assert len(tracks) == 0
    finally:
        session.close()
