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

namespace DeepDrftPublic.Client.ViewModels;

/// <summary>
/// State for the Cut album-detail page (/cuts/{entryKey}). Unlike <see cref="ReleaseDetailViewModel"/>
/// (which resolves a single playable track for Session/Mix), a Cut is multi-track: it loads the
/// release and the full ordered track list for that release. The list is fetched through the
/// existing releaseId-filtered track page sorted by TrackNumber — the explicit 1-based ordinal
/// (Phase 8) that the public read both sorts on and projects onto TrackDto. Scoped; every flag is
/// reset per <see cref="Load"/> so a reused instance never bleeds across navigations.
/// </summary>
public class CutDetailViewModel
{
    private readonly IReleaseDataService _releaseData;
    private readonly ITrackDataService _trackData;

    // A Cut covers the whole album in one page. Matches the gallery's page-size convention; a single
    // album never approaches this ceiling (the API caps PageSize at 100 regardless).
    private const int AlbumPageSize = 100;

    public ReleaseDto? Release { get; private set; }
    public IReadOnlyList<TrackDto> Tracks { get; private set; } = [];
    public bool IsLoading { get; private set; } = true;
    public bool NotFound { get; private set; }

    public CutDetailViewModel(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, IReadOnlyList<TrackDto> tracks)
    {
        Release = release;
        Tracks = tracks;
        NotFound = false;
        IsLoading = false;
    }

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

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

            Release = release;

            // The album's tracks via the releaseId-filtered 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), so use the resolved release.Id here. Sorted by TrackNumber so rows render
            // in saved order. A Cut with no streamable tracks simply leaves the list empty (the page
            // renders the header with no rows).
            var trackResult = await _trackData.GetPage(
                pageNumber: 1,
                pageSize: AlbumPageSize,
                sortColumn: "TrackNumber",
                releaseId: release.Id);
            if (trackResult is { Success: true, Value: { Items: { } items } })
                Tracks = items.ToList();
        }
        finally
        {
            IsLoading = false;
        }
    }
}
