using DntSite.Web.Features.AppConfigs.Entities;
using DntSite.Web.Features.AppConfigs.Models;
using DntSite.Web.Features.AppConfigs.ModelsMappings;
using DntSite.Web.Features.AppConfigs.Services.Contracts;
using DntSite.Web.Features.Common.Services.Contracts;
using DntSite.Web.Features.Persistence.UnitOfWork;

namespace DntSite.Web.Features.AppConfigs.Services;

public class AppSettingsService(
    IUnitOfWork uow,
    IEmailsFactoryService emailsFactoryService,
    ICachedAppSettingsProvider cachedAppSettingsProvider) : IAppSettingsService
{
    private readonly DbSet<AppSetting> _blogConfigs = uow.DbSet<AppSetting>();

    public async Task<bool> IsBannedReferrerAsync(string? url)
    {
        if (url.IsEmpty())
        {
            return false;
        }

        var config = await cachedAppSettingsProvider.GetAppSettingsAsync();

        if (config.BannedReferrers?.Count == 0)
        {
            return false;
        }

        var bannedReferrers = config.BannedReferrers ?? [];

        return bannedReferrers.Any(pattern => url.Contains(pattern, StringComparison.OrdinalIgnoreCase));
    }

    public async Task<bool> IsBannedDomainAndSubDomainAsync(string url)
    {
        var config = await cachedAppSettingsProvider.GetAppSettingsAsync();

        if (!url.IsValidUrl())
        {
            return true;
        }

        if (config.BannedUrls?.Count == 0)
        {
            return false;
        }

        var urls = config.BannedUrls ?? [];

        foreach (var bannedUrl in urls)
        {
            if (!bannedUrl.IsValidUrl())
            {
                continue;
            }

            if (new Uri(bannedUrl).HaveTheSameDomain(new Uri(url)))
            {
                return true;
            }
        }

        return false;
    }

    public async Task<bool> IsBannedSiteAsync(string url)
    {
        var config = await cachedAppSettingsProvider.GetAppSettingsAsync();

        if (!url.IsValidUrl())
        {
            return true;
        }

        if (config.BannedSites?.Count == 0)
        {
            return false;
        }

        var urls = config.BannedSites ?? [];

        foreach (var bannedUrl in urls)
        {
            if (!bannedUrl.IsValidUrl())
            {
                continue;
            }

            if (new Uri(bannedUrl).Host.Equals(new Uri(url).Host, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }

        return false;
    }

    public AppSetting AddAppSetting(AppSetting data) => _blogConfigs.Add(data).Entity;

    public async Task AddOrUpdateAppSettingsAsync(AppSettingModel? model)
    {
        ArgumentNullException.ThrowIfNull(model);

        var cfg = await _blogConfigs.OrderBy(x => x.Id).FirstOrDefaultAsync();

        if (cfg is null || cfg.Id == 0)
        {
            var newCfg = model.MapAppSettingModelToAppSetting();
            AddAppSetting(newCfg);
        }
        else
        {
            model.MapAppSettingModelToAppSetting(cfg);
        }

        await uow.SaveChangesAsync();

        cachedAppSettingsProvider.InvalidateAppSettings();

        await emailsFactoryService.SendTextToAllAdminsAsync(text: "تنظیمات سایت با موفقیت ویرایش گردید");
    }

    public async Task<AppSettingModel> GetAppSettingModelAsync()
    {
        var cfg = await cachedAppSettingsProvider.GetAppSettingsAsync();

        return cfg.MapAppSettingToAppSettingModel();
    }

    public async Task ChangeSiteActiveStateAsync(bool siteIsActive)
    {
        var cfg = await _blogConfigs.OrderBy(x => x.Id).FirstOrDefaultAsync();

        if (cfg is null || cfg.Id == 0 || cfg.SiteIsActive == siteIsActive)
        {
            return;
        }

        cfg.SiteIsActive = siteIsActive;
        await uow.SaveChangesAsync();
        cachedAppSettingsProvider.InvalidateAppSettings();

        await emailsFactoryService.SendTextToAllAdminsAsync(siteIsActive
            ? "سایت مجددا فعال شد."
            : "سایت به صورت موقت به علت عدم حضور مدیران غیرفعال شد. برای فعالسازی مجدد آن فقط کافی است به سایت لاگین کنید.");
    }
}
