using Hotline.File;
using Hotline.Orders;
using Hotline.Repository.SqlSugar.DataPermissions;
using Hotline.Share.Dtos.File;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using Hotline.Share.Dtos.Snapshot;
using Mapster;
using MapsterMapper;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using SqlSugar;
using System.Threading;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Repository.SqlSugar.File
{
    public class FileRepository : BaseRepository<Hotline.File.File>, IFileRepository, IScopeDependency
	{
		private readonly ISessionContext _sessionContext;
		private readonly IMapper _mapper;
		public FileRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, ISessionContext sessionContext, IMapper mapper, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
		{
			_sessionContext = sessionContext;
			_mapper = mapper;
		}

        public async Task<List<FileJson>> AddFileAsync(IList<SnapshotFileInDto> files, string id, CancellationToken requestAborted)
        {
			var entities = files.Adapt<List<Hotline.File.File>>();
			foreach (var file in entities)
			{
				var names = file.FileName.Split(".");
                //file.Name = names[0];
                file.Type = names[names.Length-1];
				file.Name = file.FileName.Replace("."+file.Type, "");
				file.Key = id;
                file.OrgName = _sessionContext.OrgName;
                file.OrgId = _sessionContext.OrgId;
                file.UserId = _sessionContext.UserId;
                file.UserName = _sessionContext.UserName;
            }
            await AddRangeAsync(entities, requestAborted);
            return entities.Select(x => new FileJson { Id = x.Id, FileId = x.Additions, Path = x.Path, FileName = x.Name, FileType = x.Type }).ToList();
        }

		public async Task<List<FileJson>> AddFileAsync(IList<FileDto> files, string id, CancellationToken requestAborted)
		{
			var entities = files.Adapt<List<Hotline.File.File>>();
			foreach (var file in entities)
			{
				var names = file.FileName.Split(".");
				//file.Name = names[0];
				//file.Type = names[1];
				file.Type = names[names.Length - 1];
				file.Name = file.FileName.Replace("." + file.Type, "");
				file.Key = id;
				file.OrgName = _sessionContext.OrgName;
				file.OrgId = _sessionContext.OrgId;
				file.UserId = _sessionContext.UserId;
				file.UserName = _sessionContext.UserName;
			}
			await AddRangeAsync(entities, requestAborted);
			return entities.Select(x => new FileJson { Id = x.Id, FileId = x.Additions, Path = x.Path, FileName = x.Name, FileType = x.Type }).ToList();
		}

		public async Task<List<FileJson>> AddFileAsync(List<FileDto> files, string id, string flowId = "", CancellationToken cancellationToken = default) 
		{
			List<Hotline.File.File> newFiles =  new List<Hotline.File.File>();
			var classify = files[0].Classify;
			var query = Db.Queryable<Hotline.File.File>().Where(x => x.Key == id && x.Classify == classify);
			if (!string.IsNullOrEmpty(flowId)) query.Where(x => x.FlowKey == flowId);
			var deleteFilesId = await query.Select(x=>x.Id).ToListAsync(cancellationToken);
			await Db.Deleteable<Hotline.File.File>().In(x=>x.Id , deleteFilesId).ExecuteCommandAsync(cancellationToken);
			foreach (FileDto file in files)
			{
				if (string.IsNullOrEmpty(file.Path) || string.IsNullOrEmpty(file.AllPath))
					throw UserFriendlyException.SameMessage("附件信息错误,请检查后重新上传附件！");
				var names = file.FileName.Split(".");
				//file.Name = names[0];
				//file.Type = names[1];
				file.Type = names[names.Length - 1];
				file.Name = file.FileName.Replace("." + file.Type, "");
				file.OrgName = _sessionContext.OrgName;
				file.OrgId = _sessionContext.OrgId;
				file.UserId = _sessionContext.UserId;
				file.UserName = _sessionContext.UserName;
				file.FlowKey = flowId;
				file.Key = id;
				var model = _mapper.Map<Hotline.File.File>(file);
				newFiles.Add(model);
			}
			await AddRangeAsync(newFiles, cancellationToken);
			return newFiles.Select(x=> new FileJson { Id = x.Id,FileId = x.Additions,Path = x.Path,FileName =x.Name ,FileType =x.Type}).ToList();
		}

		public async Task<List<FileDto>> GetFilesAsync(List<string> ids, CancellationToken cancellationToken = default) 
		{
			var files = await Queryable().In(x => x.Id, ids).ToListAsync(cancellationToken);
			return files.Any() ? _mapper.Map<List<FileDto>>(files) : new List<FileDto>();
		}

		public async Task<List<FileDto>> GetPermissionFilesAsync(List<string> ids, CancellationToken cancellationToken = default)
		{
			var files  = await Queryable().In(x => x.Id, ids).Where(x => x.CreatorOrgId.StartsWith(_sessionContext.RequiredOrgId)).ToListAsync(cancellationToken);
			return files.Any() ? _mapper.Map<List<FileDto>>(files) : new List<FileDto>();
		}

		public async Task<List<Hotline.File.File>> GetByKeyAsync(string key, CancellationToken cancellationToken)
		{ 
			return await Queryable().Where(x => x.Key == key && x.IsDeleted == false).ToListAsync(cancellationToken);
        }

		public async Task<List<WorkflowTraceDto>> WorkflowTraceRecursion(List<WorkflowTraceDto> dto, CancellationToken cancellationToken)
		{
			foreach (var item in dto)
			{
				if (item.FileJson != null && item.FileJson.Any())
				{
					var ids = item.FileJson.Select(x => x.Id).ToList();
					item.Files = await GetFilesAsync(ids, cancellationToken);
				}

				if (item.Traces != null && item.Traces.Any()) 
                    item.Traces =  await WorkflowTraceRecursion(item.Traces, cancellationToken);
			}
			return dto;
		}

    }
}
