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


namespace OF_DL.Models.Mappers;

public static class PostMapper
{
    public static Post FromDto(PostDto? dto)
    {
        Post 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;
    }

    public static SinglePost FromDto(SinglePostDto? dto)
    {
        SinglePost mapped = new();

        if (dto == null)
        {
            return mapped;
        }

        mapped.Id = dto.Id;
        mapped.PostedAt = dto.PostedAt;
        mapped.Author = MapSingleAuthor(dto.Author);
        mapped.Text = dto.Text;
        mapped.RawText = dto.RawText;
        mapped.IsOpened = dto.IsOpened;
        mapped.Price = dto.Price;
        mapped.IsArchived = dto.IsArchived;
        mapped.Media = MapSingleMedia(dto.Media);
        mapped.Preview = dto.Preview;

        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,
            IsOpened = dto.IsOpened,
            Price = dto.Price,
            IsArchived = dto.IsArchived,
            Media = MapMedia(dto.Media),
            Preview = dto.Preview
        };

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

    private static Author? MapSingleAuthor(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,
            Preview = dto.Preview,
            Files = MapFiles(dto.Files)
        };

    private static Files? MapFiles(FilesDto? dto) => dto == null
        ? null
        : new Files { Full = MapFull(dto.Full), Preview = MapPreview(dto.Preview), Drm = MapDrm(dto.Drm) };

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

    private static Preview? MapPreview(PreviewDto? dto) =>
        dto == null || string.IsNullOrEmpty(dto.Url) ? null : new Preview { Url = dto.Url };

    private static Drm MapDrm(DrmDto? dto) => new()
    {
        Manifest = MapManifest(dto?.Manifest), Signature = MapSignature(dto?.Signature)
    };

    private static Manifest? MapManifest(ManifestDto? dto) =>
        dto == null ? null : new Manifest { Dash = dto.Dash };

    private static Signature? MapSignature(SignatureDto? dto) =>
        dto == null ? null : new Signature { Dash = MapDash(dto.Dash) };

    private static Dash? MapDash(DashDto? dto)
    {
        if (dto == null)
        {
            return null;
        }

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

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

    private static Medium MapSingleMedium(MediumDto dto) =>
        new()
        {
            Id = dto.Id,
            Type = dto.Type,
            CanView = dto.CanView,
            Preview = dto.Preview,
            Files = MapSingleFiles(dto.Files),
            VideoSources = MapVideoSources(dto.VideoSources)
        };

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

        return new Files
        {
            Full = MapSingleFull(dto.Full), Preview = MapSinglePreview(dto.Preview), Drm = MapSingleDrm(dto.Drm)
        };
    }

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

    private static Preview? MapSinglePreview(PreviewDto? dto) =>
        dto == null || string.IsNullOrEmpty(dto.Url) ? null : new Preview { Url = dto.Url };

    private static Drm? MapSingleDrm(DrmDto? dto) => dto == null
        ? null
        : new Drm { Manifest = MapSingleManifest(dto.Manifest), Signature = MapSingleSignature(dto.Signature) };

    private static Manifest? MapSingleManifest(ManifestDto? dto) =>
        dto == null ? null : new Manifest { Dash = dto.Dash };

    private static Signature? MapSingleSignature(SignatureDto? dto) =>
        dto == null ? null : new Signature { Dash = MapSingleDash(dto.Dash) };

    private static Dash? MapSingleDash(DashDto? dto)
    {
        if (dto == null)
        {
            return null;
        }

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

    private static VideoSources? MapVideoSources(VideoSourcesDto? dto) => dto == null
        ? null
        : new VideoSources { _240 = dto._240, _720 = dto._720 };
}
