using DeepDrftModels.DTOs;
using DeepDrftPublic.Client.Services;

namespace DeepDrftPublic.Client.ViewModels;

/// <summary>
/// State for a single-release detail page (Session, Mix). Loads the release and resolves its
/// playable track. The release read surface exposes no track entry directly, so the playable track
/// is resolved through the existing track gallery filtered by the release's id (an exact join) — for
/// Session/Mix that yields the single track. Scoped; reset every flag per <see cref="Load"/> so a
/// reused instance never bleeds across navigations.
/// </summary>
public class ReleaseDetailViewModel
{
    private readonly IReleaseDataService _releaseData;
    private readonly ITrackDataService _trackData;

    public ReleaseDto? Release { get; private set; }
    public TrackDto? Track { get; private set; }
    public bool IsLoading { get; private set; } = true;
    public bool NotFound { get; private set; }

    public ReleaseDetailViewModel(IReleaseDataService releaseData, ITrackDataService trackData)
    {
        _releaseData = releaseData;
        _trackData = trackData;
    }

    /// <summary>Seed state directly from a bridged prerender payload — no fetch.</summary>
    public void Restore(ReleaseDto release, TrackDto? track)
    {
        Release = release;
        Track = track;
        NotFound = false;
        IsLoading = false;
    }

    public async Task Load(string entryKey)
    {
        IsLoading = true;
        NotFound = false;
        Release = null;
        Track = null;

        try
        {
            var releaseResult = await _releaseData.GetByEntryKey(entryKey);
            if (releaseResult is not { Success: true, Value: { } release })
            {
                NotFound = true;
                return;
            }

            Release = release;

            // Resolve the playable track via the releaseId-filtered track page — an exact join, not a
            // title string (which collides across same-titled releases and breaks on rename). The public
            // page addresses the release by EntryKey; the track→release join stays on the internal int
            // FK (Phase 11 §3e leaves internal joins on the int PK), so use the resolved release.Id here.
            // Session/Mix releases carry a single track; take the first. A release with no streamable
            // track simply leaves Track null (the detail page hides the play affordance).
            var trackResult = await _trackData.GetPage(
                pageNumber: 1, pageSize: 1, releaseId: release.Id);
            if (trackResult is { Success: true, Value: { Items: { } items } })
                Track = items.FirstOrDefault();
        }
        finally
        {
            IsLoading = false;
        }
    }
}
