using System.Text;
using DntSite.Web.Features.AppConfigs.Services.Contracts;
using DntSite.Web.Features.News.Entities;
using DntSite.Web.Features.News.Models;
using DntSite.Web.Features.News.RoutingConstants;
using DntSite.Web.Features.RssFeeds.Models;

namespace DntSite.Web.Features.News.ModelsMappings;

public static class NewsMappersExtensions
{
    public static readonly CompositeFormat ParsedPostUrlTemplate =
        CompositeFormat.Parse(NewsRoutingConstants.PostUrlTemplate);

    public static WhatsNewItemModel MapToWhatsNewItemModel(this DailyNewsItemComment item,
        string siteRootUri,
        bool showBriefDescription)
    {
        ArgumentNullException.ThrowIfNull(item);

        return new WhatsNewItemModel
        {
            User = item.User,
            AuthorName = item.User?.FriendlyName ?? item.GuestUser.UserName,
            Content = showBriefDescription ? item.Body.GetBriefDescription(charLength: 450) : item.Body,
            PublishDate = new DateTimeOffset(item.Audit.CreatedAt),
            LastUpdatedTime =
                new DateTimeOffset(item.AuditActions.Count > 0
                    ? item.AuditActions[^1].CreatedAt
                    : item.Audit.CreatedAt),
            Title = $"{WhatsNewItemType.NewsComments.Value}: {item.Parent.Title}",
            OriginalTitle = item.Parent.Title,
            Url = siteRootUri.CombineUrl(
                string.Create(CultureInfo.InvariantCulture,
                    $"{NewsRoutingConstants.NewsDetailsBase}/{item.ParentId}#comment-{item.Id}"),
                escapeRelativeUrl: false),
            Categories = [],
            ItemType = WhatsNewItemType.NewsComments,
            Id = item.Id,
            UserId = item.UserId,
            EntityType = item.GetType()
        };
    }

    public static WhatsNewItemModel MapToAuthorWhatsNewItemModel(this DailyNewsItem item,
        bool showBriefDescription,
        string siteRootUri = "",
        string newsThumbImage = "")
    {
        ArgumentNullException.ThrowIfNull(item);

        return new WhatsNewItemModel
        {
            User = item.User,
            AuthorName = item.User?.FriendlyName ?? item.GuestUser.UserName,
            Content = showBriefDescription
                ? item.BriefDescription.GetBriefDescription(charLength: 450)
                : $"{item.BriefDescription} {newsThumbImage}",
            PublishDate = new DateTimeOffset(item.Audit.CreatedAt),
            LastUpdatedTime =
                new DateTimeOffset(item.AuditActions.Count > 0
                    ? item.AuditActions[^1].CreatedAt
                    : item.Audit.CreatedAt),
            Title = $"{WhatsNewItemType.NewsAuthor.Value}: {item.Title}",
            OriginalTitle = item.Title,
            Url = siteRootUri.CombineUrl(
                string.Create(CultureInfo.InvariantCulture, $"{NewsRoutingConstants.NewsDetailsBase}/{item.Id}"),
                escapeRelativeUrl: false),
            Categories = [..item.Tags.Select(x => x.Name)],
            ItemType = WhatsNewItemType.NewsAuthor,
            Id = item.Id,
            UserId = item.UserId,
            EntityType = item.GetType()
        };
    }

    public static WhatsNewItemModel MapToNewsWhatsNewItemModel(this DailyNewsItem item,
        bool showBriefDescription,
        string siteRootUri = "",
        string newsThumbImage = "")
    {
        ArgumentNullException.ThrowIfNull(item);

        return new WhatsNewItemModel
        {
            User = item.User,
            AuthorName = item.User?.FriendlyName ?? item.GuestUser.UserName,
            Content = showBriefDescription
                ? item.BriefDescription.GetBriefDescription(charLength: 450)
                : $"{item.BriefDescription} {newsThumbImage}",
            PublishDate = new DateTimeOffset(item.Audit.CreatedAt),
            LastUpdatedTime =
                new DateTimeOffset(item.AuditActions.Count > 0
                    ? item.AuditActions[^1].CreatedAt
                    : item.Audit.CreatedAt),
            Title = $"{WhatsNewItemType.News.Value}: {item.Title}",
            OriginalTitle = item.Title,
            Url = siteRootUri.CombineUrl(string.Format(CultureInfo.InvariantCulture, ParsedPostUrlTemplate, item.Id),
                escapeRelativeUrl: false),
            Categories = [..item.Tags.Select(x => x.Name)],
            ItemType = WhatsNewItemType.News,
            Id = item.Id,
            UserId = item.UserId,
            EntityType = item.GetType()
        };
    }

    public static DailyNewsItem MapDailyNewsItemModelToDailyNewsItem(this DailyNewsItemModel source,
        IAppAntiXssService antiXssService,
        IUrlNormalizationService urlNormalizationService,
        IPasswordHasherService passwordHasherService,
        DailyNewsItem? destination = null)
    {
        ArgumentNullException.ThrowIfNull(source);
        ArgumentNullException.ThrowIfNull(antiXssService);
        ArgumentNullException.ThrowIfNull(urlNormalizationService);
        ArgumentNullException.ThrowIfNull(passwordHasherService);

        var dailyNewsItem = new DailyNewsItem
        {
            Title = source.Title,
            BriefDescription = antiXssService.GetSanitizedHtml(source.DescriptionText),
            UrlHash = passwordHasherService.GetSha1Hash(urlNormalizationService.NormalizeUrl(source.Url.Trim())),
            Url = source.Url
        };

        if (destination is not null)
        {
            destination.Title = dailyNewsItem.Title;
            destination.BriefDescription = dailyNewsItem.BriefDescription;
            destination.UrlHash = dailyNewsItem.UrlHash;
            destination.Url = dailyNewsItem.Url;
        }

        return destination ?? dailyNewsItem;
    }

    public static DailyNewsItemModel MapDailyNewsItemToDailyNewsItemModel(this DailyNewsItem source)
    {
        ArgumentNullException.ThrowIfNull(source);

        return new DailyNewsItemModel
        {
            Title = source.Title,
            DescriptionText = source.BriefDescription ?? "",
            Url = source.Url,
            Tags = source.Tags?.Select(tag => tag.Name).ToList() ?? []
        };
    }
}
