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 orchestrator built on the BlazorBlocks Manager base. Two surfaces coexist:
///
/// - The DTO-shaped IManager surface (GetById → TrackDto, etc.) inherited from Manager<>.
/// - The entity-shaped ITrackService surface retained for backward compatibility with the
/// web host, CMS, and CLI — all existing controllers and pages inject ITrackService and
/// expect TrackEntity-typed results. The two GetById overloads conflict on signature, so
/// ITrackService.GetById is implemented explicitly; the base Manager.Delete satisfies
/// both interfaces because the signatures align.
///
public class TrackManager
: Manager, ITrackService
{
public TrackManager(
TrackRepository repository,
ILogger> logger)
: base(repository, logger)
{
}
// --- ITrackService implementation (entity-space; calls Repository directly) ---
// Explicit interface implementation — IManager.GetById returns ResultContainer
// (inherited from Manager<>), so this entity-typed overload cannot coexist as a public
// member with the same name. Callers always inject ITrackService, so the explicit impl
// resolves correctly at the call site.
async Task> ITrackService.GetById(long id)
{
try
{
var entity = await Repository.GetByIdAsync(id);
return ResultContainer.CreatePassResult(entity);
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
public async Task>> GetAll()
{
try
{
var entities = await Repository.GetAllAsync();
return ResultContainer>.CreatePassResult(entities.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);
return ResultContainer>.CreatePassResult(page);
}
catch (Exception e)
{
return ResultContainer>.CreateFailResult(e.Message);
}
}
public async Task> Create(TrackEntity newTrack)
{
try
{
var added = await Repository.AddAsync(newTrack);
return ResultContainer.CreatePassResult(added);
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
// Manager<>.Update takes TrackDto and returns Result; this Update keeps the
// entity-typed contract callers expect and returns the post-update entity for the
// existing CMS edit flow that reads back the persisted values.
///
/// Updates the track's metadata fields and returns the DB-authoritative entity.
/// The caller's object has its UpdatedAt field
/// mutated in place by ; do not reuse it.
///
public async Task> Update(TrackEntity track)
{
try
{
await Repository.UpdateAsync(track);
var updated = await Repository.GetByIdAsync(track.Id);
return updated is not null
? ResultContainer.CreatePassResult(updated)
: ResultContainer.CreateFailResult("Track not found after update.");
}
catch (Exception e)
{
return ResultContainer.CreateFailResult(e.Message);
}
}
// Delete(long) is inherited from Manager<> — its Task signature already
// satisfies ITrackService.Delete, and the base implementation performs the soft delete
// via Repository.DeleteAsync. No override needed.
}