using DeepDrftModels.DTOs;
using DeepDrftModels.Entities;
using DeepDrftModels.Enums;
using Models.Converters;

namespace DeepDrftData;

/// <summary>
/// Static entity ↔ DTO converter consumed by the BlazorBlocks Manager base class.
/// The DTO side mirrors the entity field-for-field; the audit columns
/// (CreatedAt, UpdatedAt) come from BaseEntity / BaseModel.
/// IsDeleted does not round-trip — soft-deleted rows are not exposed via the model.
///
/// Post Phase 8 §8.0: TrackEntity carries only track-cardinal fields plus a nullable
/// ReleaseId/Release. The release-cardinal data converts through the Release maps below.
/// </summary>
public class TrackConverter : IEntityToModelConverter<TrackEntity, TrackDto>
{
    public static ReleaseDto Convert(ReleaseEntity entity) => new()
    {
        Id = entity.Id,
        EntryKey = entity.EntryKey,
        CreatedAt = entity.CreatedAt,
        UpdatedAt = entity.UpdatedAt,
        Title = entity.Title,
        Artist = entity.Artist,
        Genre = entity.Genre,
        Description = entity.Description,
        ReleaseDate = entity.ReleaseDate,
        ImagePath = entity.ImagePath,
        Medium = entity.Medium,
        // ReleaseType is meaningful only for Cut; null it for Session/Mix at the mapping point so no
        // consumer mistakes a stale studio-format value for a live/mix release.
        ReleaseType = entity.Medium == ReleaseMedium.Cut ? entity.ReleaseType : (ReleaseType?)null,
        SessionMetadata = entity.SessionMetadata is null
            ? null
            : new SessionMetadataDto
            {
                ReleaseId = entity.SessionMetadata.ReleaseId,
                HeroImageEntryKey = entity.SessionMetadata.HeroImageEntryKey
            },
        MixMetadata = entity.MixMetadata is null
            ? null
            : new MixMetadataDto
            {
                ReleaseId = entity.MixMetadata.ReleaseId,
                WaveformEntryKey = entity.MixMetadata.WaveformEntryKey
            },
        CreatedByUserId = entity.CreatedByUserId
    };

    public static ReleaseEntity Convert(ReleaseDto dto) => new()
    {
        Id = dto.Id,
        // Round-trips the public handle. On the create path (FindOrCreateRelease) the DTO carries no
        // EntryKey yet, so that path overrides this with a freshly minted GUID — the same shape as the
        // natural-key (Title/Artist) override there.
        EntryKey = dto.EntryKey,
        CreatedAt = dto.CreatedAt,
        UpdatedAt = dto.UpdatedAt,
        Title = dto.Title,
        Artist = dto.Artist,
        Genre = dto.Genre,
        Description = dto.Description,
        ReleaseDate = dto.ReleaseDate,
        ImagePath = dto.ImagePath,
        Medium = dto.Medium,
        // Entity ReleaseType is non-nullable; default back to Single when the DTO nulled it for a
        // non-Cut release. Primarily a write-path reconstruction concern.
        ReleaseType = dto.ReleaseType ?? ReleaseType.Single,
        CreatedByUserId = dto.CreatedByUserId
    };

    public static TrackDto Convert(TrackEntity entity) => new()
    {
        Id = entity.Id,
        CreatedAt = entity.CreatedAt,
        UpdatedAt = entity.UpdatedAt,
        EntryKey = entity.EntryKey,
        TrackName = entity.TrackName,
        OriginalFileName = entity.OriginalFileName,
        TrackNumber = entity.TrackNumber,
        DurationSeconds = entity.DurationSeconds,
        ReleaseId = entity.ReleaseId,
        Release = entity.Release is null ? null : Convert(entity.Release)
    };

    // DTO → entity maps track-cardinal fields + ReleaseId only. The Release navigation is left
    // unset: the manager resolves/attaches the release row against the tracked context so a detached
    // graph never overwrites a shared release record.
    public static TrackEntity Convert(TrackDto model) => new()
    {
        Id = model.Id,
        CreatedAt = model.CreatedAt,
        UpdatedAt = model.UpdatedAt,
        EntryKey = model.EntryKey,
        TrackName = model.TrackName,
        OriginalFileName = model.OriginalFileName,
        TrackNumber = model.TrackNumber,
        DurationSeconds = model.DurationSeconds,
        ReleaseId = model.ReleaseId
    };
}
