using DeepDrftContent.Constants;
using DeepDrftContent.FileDatabase.Services;
using DeepDrftContent.FileDatabase.Models;
using DeepDrftContent.Processors;
using DeepDrftModels.Entities;
namespace DeepDrftContent;
///
/// Service for managing tracks in both SQL and FileDatabase
///
public class TrackContentService
{
private readonly FileDatabase.Services.FileDatabase _fileDatabase;
private readonly AudioProcessorRouter _audioProcessorRouter;
public TrackContentService(FileDatabase.Services.FileDatabase fileDatabase, AudioProcessorRouter audioProcessorRouter)
{
_fileDatabase = fileDatabase;
_audioProcessorRouter = audioProcessorRouter;
}
///
/// Adds a new track from a supported audio file (.wav, .mp3, .flac) to both databases. The
/// router selects the processor by extension; original bytes are stored for mp3/flac (no
/// transcoding), while EXTENSIBLE WAVs are normalized to standard PCM at storage time.
///
/// Path to the audio file
/// Name of the track
/// Artist name
/// Optional album name
/// Optional genre
/// Optional release date
/// Optional original browser filename captured at upload time
/// The track entity with generated ID and media path
public async Task AddTrackAsync(
string audioFilePath,
string trackName,
string artist,
string? album = null,
string? genre = null,
DateOnly? releaseDate = null,
string? originalFileName = null)
{
try
{
// Process the audio file (routed by extension)
var audioBinary = await _audioProcessorRouter.ProcessAudioFileAsync(audioFilePath);
if (audioBinary == null)
{
throw new InvalidOperationException("Failed to process audio file");
}
// Generate a unique track ID
var trackId = Guid.NewGuid().ToString();
// Ensure tracks vault exists
if (!_fileDatabase.HasVault(VaultConstants.Tracks))
{
await _fileDatabase.CreateVaultAsync(VaultConstants.Tracks, MediaVaultType.Audio);
}
// Store the audio in FileDatabase
var success = await _fileDatabase.RegisterResourceAsync(VaultConstants.Tracks, trackId, audioBinary);
if (!success)
{
throw new InvalidOperationException("Failed to store audio in FileDatabase");
}
// Create the track entity for SQL database
var trackEntity = new TrackEntity
{
EntryKey = trackId, // FileDatabase entry ID
TrackName = trackName,
Artist = artist,
Album = album,
Genre = genre,
ReleaseDate = releaseDate,
OriginalFileName = originalFileName
};
return trackEntity;
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Console.WriteLine($"TrackContentService.AddTrackAsync failed: {ex.Message}");
return null;
}
}
///
/// Backward-compatible shim — delegates to . The router accepts WAV
/// alongside MP3 and FLAC, so this carries no WAV-specific logic of its own.
///
public Task AddTrackFromWavAsync(
string wavFilePath,
string trackName,
string artist,
string? album = null,
string? genre = null,
DateOnly? releaseDate = null,
string? originalFileName = null) =>
AddTrackAsync(wavFilePath, trackName, artist, album, genre, releaseDate, originalFileName);
///
/// Retrieves audio binary from FileDatabase
///
/// Track ID (EntryKey)
/// Audio binary or null if not found
public async Task GetAudioBinaryAsync(string trackId)
{
return await _fileDatabase.LoadResourceAsync(VaultConstants.Tracks, trackId);
}
///
/// Checks if FileDatabase is available and tracks vault exists
///
public bool IsFileDatabaseReady()
{
return _fileDatabase.HasVault(VaultConstants.Tracks);
}
///
/// Initializes the tracks vault if it doesn't exist
///
public async Task InitializeTracksVaultAsync()
{
if (!_fileDatabase.HasVault(VaultConstants.Tracks))
{
await _fileDatabase.CreateVaultAsync(VaultConstants.Tracks, MediaVaultType.Audio);
}
}
}