using Data.Managers;
using DeepDrftData.Repositories;
using DeepDrftModels.DTOs;
using DeepDrftModels.Entities;
using Microsoft.Extensions.Logging;
using Models.Common;
using NetBlocks.Models;
namespace DeepDrftData;
///
/// SQL-side track service built on the BlazorBlocks Manager base. The layer boundary:
/// TrackRepository outputs entities; this service outputs DTOs via TrackConverter — the
/// single authoritative entity↔DTO conversion path. The ITrackService surface is DTO-typed
/// throughout; the entity never escapes the service layer.
///
/// The base Manager<> surface does not line up with ITrackService by signature (base
/// Add vs Create, base Update→Result vs Update→DTO, base Get/GetPage vs GetAll/GetPaged,
/// base GetById→TDto vs GetById→TDto?), so the query and mutation methods are implemented
/// here over Repository + TrackConverter. Only Delete(long)→Result is inherited unchanged.
///
public class TrackManager
: Manager, ITrackService
{
public TrackManager(
TrackRepository repository,
ILogger> logger)
: base(repository, logger)
{
}
// Explicit impl: base GetById returns ResultContainer (fails on miss); the
// service contract is ResultContainer (pass with null on miss). Return types
// differ, so this cannot be a public overload of the inherited member.
async Task> ITrackService.GetById(long id)
{
try
{
var entity = await Repository.GetByIdAsync(id);
return ResultContainer.CreatePassResult(
entity is null ? null : TrackConverter.Convert(entity));
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
// Lookup by vault entry key. No base-name conflict (unlike GetById), so this is a plain
// public method. Mirrors the nullable-on-miss shape of ITrackService.GetById.
public async Task> GetByEntryKey(string entryKey)
{
try
{
var entity = await Repository.GetByEntryKeyAsync(entryKey);
return ResultContainer.CreatePassResult(
entity is null ? null : TrackConverter.Convert(entity));
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
public async Task>> GetAll()
{
try
{
var entities = await Repository.GetAllAsync();
return ResultContainer>.CreatePassResult(
entities.Select(TrackConverter.Convert).ToList());
}
catch (Exception e)
{
return ResultContainer>.CreateFailResult(e.Message);
}
}
public async Task>> GetPaged(
int pageNumber,
int pageSize,
string? sortColumn,
bool sortDescending,
CancellationToken cancellationToken = default)
{
try
{
var parameters = new PagingParameters
{
Page = pageNumber,
PageSize = pageSize,
IsDescending = sortDescending,
OrderBy = sortColumn switch
{
"TrackName" => e => e.TrackName,
"Artist" => e => e.Artist,
"Album" => e => (object)(e.Album ?? string.Empty),
"Genre" => e => (object)(e.Genre ?? string.Empty),
"ReleaseDate" => e => (object)(e.ReleaseDate ?? DateOnly.MaxValue),
_ => e => e.Id
}
};
var page = await Repository.GetPagedAsync(parameters);
var dtoPage = PagedResult.From(page, page.Items.Select(TrackConverter.Convert));
return ResultContainer>.CreatePassResult(dtoPage);
}
catch (Exception e)
{
return ResultContainer>.CreateFailResult(e.Message);
}
}
public async Task> Create(TrackDto newTrack)
{
try
{
var added = await Repository.AddAsync(TrackConverter.Convert(newTrack));
return ResultContainer.CreatePassResult(TrackConverter.Convert(added));
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
// Explicit impl: base Update returns Result; the service contract returns the persisted
// DTO so the CMS edit flow reads back DB-authoritative values.
async Task> ITrackService.Update(TrackDto track)
{
try
{
await Repository.UpdateAsync(TrackConverter.Convert(track));
var updated = await Repository.GetByIdAsync(track.Id);
return updated is not null
? ResultContainer.CreatePassResult(TrackConverter.Convert(updated))
: ResultContainer.CreateFailResult("Track not found after update.");
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
// Delete(long) → Result is inherited from Manager<> and satisfies ITrackService.Delete
// by signature. No override.
}