using DotNetCore.CAP;
using Hotline.Application.Snapshot.Contracts;
using Hotline.Caching.Interfaces;
using Hotline.Orders;
using Hotline.Settings;
using Hotline.Share.Attributes;
using Hotline.Share.Dtos.Article;
using Hotline.Share.Dtos.Snapshot;
using Hotline.Share.Enums.Article;
using Hotline.Share.Enums.Snapshot;
using Hotline.Share.Tools;
using Hotline.Snapshot;
using Hotline.Snapshot.Contracts;
using Hotline.Snapshot.IRepository;
using Mapster;
using SqlSugar;
using System.Text;
using System.Text.RegularExpressions;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;

namespace Hotline.Application.Snapshot;
public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeDependency
{

    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
    private readonly ISnapshotBulletinRepository _bulletinRepository;
    private readonly INotificationDomainService _notificationDomainService;
    private readonly ISessionContext _sessionContext;
    private readonly ISafetyTypeRepository _safetyTypeRepository;
    private readonly ICapPublisher _capPublisher;

    public SnapshotBulletinApplication(ISystemSettingCacheManager systemSettingCacheManager, ISnapshotBulletinRepository bulletinRepository, INotificationDomainService notificationDomainService, ISessionContext sessionContext, ISafetyTypeRepository safetyTypeRepository, ICapPublisher capPublisher)
    {
        _systemSettingCacheManager = systemSettingCacheManager;
        _bulletinRepository = bulletinRepository;
        _notificationDomainService = notificationDomainService;
        _sessionContext = sessionContext;
        _safetyTypeRepository = safetyTypeRepository;
        _capPublisher = capPublisher;
    }

    public async Task ExamineBulletinAsync(ExamineBulletinDto dto, CancellationToken token)
    {
        var bulletin = await _bulletinRepository.GetAsync(dto.Id, token)
            ?? throw UserFriendlyException.SameMessage("无效数据");
        if (bulletin.BulletinState != EBulletinState.InReview)
            throw UserFriendlyException.SameMessage("当前状态不能审核");

        if (dto.IsPass == false)
        {
            bulletin.ExaminOpinion = dto.Reason;
            bulletin.ExaminTime = DateTime.Now;
            bulletin.ExaminManId = _sessionContext.RequiredUserId;
            bulletin.BulletinState = EBulletinState.ReviewNoPass;
            await _bulletinRepository.UpdateAsync(bulletin, token);
            return;
        }

        bulletin.BulletinState = EBulletinState.ReviewPass;
        bulletin.BulletinTime = DateTime.Now;
        bulletin.ExaminOpinion = dto.Reason;
        bulletin.ExaminTime = DateTime.Now;
        bulletin.ExaminManId = _sessionContext.RequiredUserId;
        await _bulletinRepository.UpdateAsync(bulletin, token);

        await _capPublisher.PublishAsync(Share.Mq.EventNames.BulletinIsPass, bulletin.Id, cancellationToken: token);
    }

    /// <summary>
    /// 执行发送通知公告
    /// </summary>
    /// <param name="bullutionId"></param>
    /// <param name="token"></param>
    /// <returns></returns>
    public async Task NotifyUserAsync(string bullutionId, CancellationToken token)
    {
        await _bulletinRepository.GetAsync(bullutionId, token)
            .Then(async bulletion =>
            {
                if (bulletion!.SnapshotBulletinTypeId != "aqws") return;
                if (bulletion!.SafetyTypeId!.IsNullOrEmpty()) return;
                foreach (var safetyTypeId in bulletion!.SafetyTypeId!)
                {
                    await _safetyTypeRepository.Queryable()
                        .LeftJoin<CitizenRelationSafetyType>((safety, relation) => safety.Id == relation.SafetyTypeId)
                        .LeftJoin<Citizen>((safety, relation, citizen) => relation.CitizenId == citizen.Id)
                        .Where((safety, relation, citizen) => safety.Id == safetyTypeId)
                        .Select((safety, relation, citizen) => relation.CitizenId)
                        .ToListAsync(token)
                        .Then(async citizenIds =>
                        {
                            var inDto = bulletion.Adapt<AddNotifyInDto>();
                            inDto.UserIds = citizenIds;
                            if (bulletion.Shape != null && bulletion.Shape == EBulletinShape.Video)
                            {
                                inDto.NotifyType = ENotificationType.Video;
                            }
                            inDto.ExternalId = bulletion.Id;
                            await _notificationDomainService.AddNotifyAsync(inDto, token);
                        });
                }
            });
    }

    /// <summary>
    /// 处理通知公告图片附件路径
    /// </summary>
    /// <param name="sHtmlText"></param>
    /// <returns></returns>
    public string GetSiteUrls(string sHtmlText)
    {
        sHtmlText = sHtmlText.Replace("&lt;", "<").Replace("&gt;", ">");

        //临时内容
        System.Text.StringBuilder sb = new StringBuilder();
        sb.Append(sHtmlText);
        // 定义正则表达式用来匹配 img 标签
        Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
        // 搜索匹配的字符串
        MatchCollection matches = regImg.Matches(sHtmlText);

        // 定义正则表达式用来匹配 video 标签
        Regex regvideo = new Regex(@"<video\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
        // 搜索匹配的字符串
        MatchCollection matchesvideo = regvideo.Matches(sHtmlText);

        var strSiteUrl = _systemSettingCacheManager.GetSetting(SettingConstants.OldFilesUrls)?.SettingValue[0];

        // 取得匹配项列表 视频
        foreach (Match match in matchesvideo)
        {
            if (-1 == match.Groups["imgUrl"].Value.IndexOf("http"))
            {
                sb.Replace(match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
                sb.Replace(strSiteUrl + strSiteUrl + match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
            }
        }

        // 取得匹配项列表
        foreach (Match match in matches)
        {
            if (-1 == match.Groups["imgUrl"].Value.IndexOf("http"))
            {
                sb.Replace(match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
                sb.Replace(strSiteUrl + strSiteUrl + match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
            }
        }

        return sb.ToString();
    }

    [ExportExcel("随手拍公告")]
    public ISugarQueryable<SnapshotBulletinItemsOutDto> QueryBulletinItems(SnapshotBulletinItemsInDto dto)
    {
        var query = _bulletinRepository.Queryable()
            .Includes(x => x.ExaminMan)
            .WhereIF(!string.IsNullOrEmpty(dto.SnapshotBulletinTypeName), d => d.SnapshotBulletinTypeName.Contains(dto.SnapshotBulletinTypeName))
            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
            .WhereIF(dto.BeginCreationTime.HasValue, d => d.BulletinTime >= dto.BeginCreationTime)
            .WhereIF(dto.EndCreationTime.HasValue, d => d.BulletinTime <= dto.EndCreationTime)
            .WhereIF(dto.State.HasValue, d => d.BulletinState == dto.State)
            .OrderByDescending(d => d.CreationTime)
            .Select<SnapshotBulletinItemsOutDto>();
        return query;
    }


    public async Task CommitBulletinAsync(string id, CancellationToken requestAborted)
    {
        var bulletin = await _bulletinRepository.GetAsync(id, requestAborted);
        if (bulletin == null)
            throw UserFriendlyException.SameMessage("无效数据");

        if (bulletin.BulletinState != EBulletinState.Draft && bulletin.BulletinState != EBulletinState.ReviewNoPass)
            throw UserFriendlyException.SameMessage("当前状态不能提交");

        bulletin.BulletinState = EBulletinState.InReview;
        bulletin.CommitTime = DateTime.Now;
        await _bulletinRepository.UpdateAsync(bulletin, requestAborted);
    }


    public async Task<string> AddBulletinAsync(AddSnapshotBulletinInDto dto, CancellationToken token)
    {
        var model = dto.Adapt<SnapshotBulletin>();
        model.BulletinState = EBulletinState.Draft;
        model.ReadedNum = 0;
        if (model.Content.IsNullOrEmpty())
            model.Content = " ";
        if (model.BulletinTime.HasValue == false) model.BulletinTime = DateTime.Now;
        return await _bulletinRepository.AddAsync(model, token);
    }
}
