using OF_DL.Models.Dtos.Common;
using OF_DL.Models.Dtos.Streams;
using OF_DL.Models.Entities.Common;
using OF_DL.Models.Entities.Streams;

namespace OF_DL.Models.Mappers;

public static class StreamsMapper
{
    public static Streams FromDto(StreamsDto? dto)
    {
        Streams mapped = new() { HasMore = dto?.HasMore ?? false, TailMarker = dto?.TailMarker };

        if (dto?.List == null)
        {
            return mapped;
        }

        foreach (ListItemDto entry in dto.List)
        {
            mapped.List.Add(MapList(entry));
        }

        return mapped;
    }

    private static ListItem MapList(ListItemDto dto) =>
        new()
        {
            Id = dto.Id,
            PostedAt = dto.PostedAt,
            Author = MapAuthor(dto.Author),
            Text = dto.Text,
            RawText = dto.RawText,
            Price = dto.Price,
            IsOpened = dto.IsOpened ?? false,
            IsArchived = dto.IsArchived ?? false,
            Media = MapMedia(dto.Media),
            Preview = dto.Preview
        };

    private static Author? MapAuthor(AuthorDto? dto) =>
        dto == null ? null : new Author { Id = dto.Id };

    private static List<Medium>? MapMedia(List<MediumDto>? media) =>
        media?.Select(MapMedium).ToList();

    private static Medium MapMedium(MediumDto dto) =>
        new() { Id = dto.Id, Type = dto.Type, CanView = dto.CanView, Files = MapFiles(dto.Files) };

    private static Files? MapFiles(FilesDto? dto)
    {
        if (dto == null)
        {
            return null;
        }

        Full? full = MapFull(dto.Full);
        Drm? drm = MapDrm(dto.Drm);

        if (full == null && drm == null)
        {
            return null;
        }

        return new Files { Full = full, Drm = drm };
    }

    private static Full? MapFull(FullDto? dto) =>
        dto == null || string.IsNullOrEmpty(dto.Url) ? null : new Full { Url = dto.Url };

    private static Drm? MapDrm(DrmDto? dto)
    {
        if (dto?.Manifest == null || string.IsNullOrEmpty(dto.Manifest.Dash))
        {
            return null;
        }

        Dash? dash = MapDash(dto.Signature.Dash);
        if (dash == null)
        {
            return null;
        }

        return new Drm
        {
            Manifest = new Manifest { Dash = dto.Manifest.Dash }, Signature = new Signature { Dash = dash }
        };
    }

    private static Dash? MapDash(DashDto? dto)
    {
        if (dto == null ||
            string.IsNullOrEmpty(dto.CloudFrontPolicy) ||
            string.IsNullOrEmpty(dto.CloudFrontSignature) ||
            string.IsNullOrEmpty(dto.CloudFrontKeyPairId))
        {
            return null;
        }

        return new Dash
        {
            CloudFrontPolicy = dto.CloudFrontPolicy,
            CloudFrontSignature = dto.CloudFrontSignature,
            CloudFrontKeyPairId = dto.CloudFrontKeyPairId
        };
    }
}
