using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;

namespace IRaCIS.Core.Application.Services
{
    [ApiExplorerSettings(GroupName = "Trial")]
    public class TrialMaintenanceService(IRepository<TrialSite> _trialSiteRepository,
        IRepository<TrialSiteUser> _trialSiteUserRepository,
        IRepository<Site> _siteRepository,
        IRepository<Subject> _subjectRepository,
        IRepository<VisitTask> _visitTaskRepository,
        IRepository<Trial> _trialRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ITrialSiteService
    {




        /// <summary>Pannel 进去      SiteTab </summary>
        [HttpPost]
        public async Task<PageOutput<SiteStatDTO>> GetSiteCRCList(SiteCrcQueryDTO inQuery)
        {

            var siteStatQuery = _trialSiteRepository.Where(t => t.TrialId == inQuery.TrialId, ignoreQueryFilters: true)
                              .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.TrialSiteName.Contains(inQuery.SiteName))
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteAliasName), t => t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName))
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteCode), t => t.TrialSiteCode.Contains(inQuery.TrialSiteCode))
                             .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.CRCUserList.Any(k => k.UserId == _userInfo.Id))
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserKeyInfo), t => t.CRCUserList.Any(k => (k.User.FullName).Contains(inQuery.UserKeyInfo)
                             || k.User.UserName.Contains(inQuery.UserKeyInfo) || k.User.EMail.Contains(inQuery.UserKeyInfo)))

                             .ProjectTo<SiteStatDTO>(_mapper.ConfigurationProvider);

            return await siteStatQuery.ToPagedListAsync(inQuery);


        }


        /// <summary>[new] setting页面Site列表，和getSiteCRCList对比 没有统计数据，增加了一些site信息 </summary>
        [HttpPost]
        public async Task<PageOutput<SiteStatSimpleDTO>> GetSiteCRCSimpleList(SiteCrcQueryDTO inQuery)
        {

            var siteStatQuery = _trialSiteRepository.Where(t => t.TrialId == inQuery.TrialId).IgnoreQueryFilters()
                             .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
                            .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.TrialSiteName.Contains(inQuery.SiteName) || t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName))
                            .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteAliasName), t => t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName))
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteCode), t => t.TrialSiteCode.Contains(inQuery.TrialSiteCode))
                            .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.CRCUserList.Any(k => k.UserId == _userInfo.Id))
                             .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserKeyInfo), t => t.CRCUserList.Any(k => (k.User.FullName).Contains(inQuery.UserKeyInfo)
                             || k.User.UserName.Contains(inQuery.UserKeyInfo) || k.User.EMail.Contains(inQuery.UserKeyInfo)))

                            .ProjectTo<SiteStatSimpleDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us });


            var result = await siteStatQuery.ToPagedListAsync(inQuery);

            return result;
        }


        /// <summary>获取某一Site下面的负责的CRC列表</summary>
        [HttpGet, Route("{trialId:guid}/{siteId:guid}")]
        public async Task<List<UserTrialDTO>> GetTrialSiteCRCList(Guid trialId, Guid siteId)
        {
            var query = _trialSiteUserRepository.Where(t => t.TrialId == trialId && t.TrialSiteId == siteId).IgnoreQueryFilters()
                  .ProjectTo<UserTrialDTO>(_mapper.ConfigurationProvider);

            return await query.ToListAsync();
        }


        /// <summary>[new] Setting页面   Site勾选列表（ </summary>
        [HttpPost]
        public async Task<PageOutput<TrialSiteScreeningDTO>> GetTrialSiteScreeningList(TrialSiteQuery inQuery)
        {
            // 之前选择了的不能再次出现在列表，做的时候我就不建议这样搞，搞好了  现在又要改回去。。。 瞎折腾。。。。


            var siteQueryable = _siteRepository.AsQueryable(true)
                   .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.SiteName.Contains(inQuery.SiteName) || t.SiteNameCN.Contains(inQuery.SiteName) || t.AliasName.Contains(inQuery.SiteName))
                   .WhereIf(!string.IsNullOrWhiteSpace(inQuery.AliasName), t => t.AliasName.Contains(inQuery.AliasName))
                   .WhereIf(!string.IsNullOrWhiteSpace(inQuery.City), t => t.City.Contains(inQuery.City))
                   .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Country), t => t.Country.Contains(inQuery.Country))
                   .ProjectTo<TrialSiteScreeningDTO>(_mapper.ConfigurationProvider, new { trialId = inQuery.TrialId, isEn_Us = _userInfo.IsEn_Us });


            return await siteQueryable.ToPagedListAsync(inQuery);

        }


        public async Task<List<TrialSiteSelect>> GetTrialSiteSelectList(string? siteName)
        {
            var list = _siteRepository
                 .WhereIf(!string.IsNullOrWhiteSpace(siteName), t => t.SiteName.Contains(siteName) || t.SiteNameCN.Contains(siteName) || t.AliasName.Contains(siteName))
                 .Select(t => new TrialSiteSelect() { SiteId = t.Id, SiteName = _userInfo.IsEn_Us ? t.SiteName : t.SiteNameCN, AliasName = t.AliasName }).ToList();

            return list;
        }



        /// <summary>Setting页面   Site批量添加</summary>
        [HttpPost]
        [UnitOfWork]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> AddTrialSites(List<TrialSiteCommand> trialSites)
        {
            var addArray = _mapper.Map<List<TrialSite>>(trialSites);

            foreach (var item in addArray)
            {
                if (item.IsDeleted == false)
                {
                    item.EnabledTime = DateTime.Now;
                }
            }

            await _trialSiteRepository.AddRangeAsync(addArray);


            return ResponseOutput.Result(await _trialSiteRepository.SaveChangesAsync());
        }



        /// <summary>
        /// 项目site 编辑接口 New  可以设置为启用不启用  不启用 不会验证Code 重复
        /// </summary>
        /// <param name="editTrialSiteCommand"></param>
        /// <returns></returns>
        [HttpPut]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task<IResponseOutput> EditTrialSite(EditTrialSiteCommand editTrialSiteCommand)
        {

            var dbEntity = await _trialSiteRepository.FirstOrDefaultAsync(t => t.Id == editTrialSiteCommand.Id, true);

            if (dbEntity == null) return Null404NotFound(dbEntity);

            var trialId = dbEntity.TrialId;
            var trialSiteId = dbEntity.Id;

            if (editTrialSiteCommand.IsDeleted)
            {

                if (await _trialSiteUserRepository.AnyAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId))
                {
                    //---The site has been associated with CRC, and couldn't be deleted.
                    return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedCRC"]);
                }

                if (await _subjectRepository.AnyAsync(t => t.TrialSiteId == trialSiteId && t.TrialId == trialId))
                {
                    //---The subjects has been added to  this site, and couldn't be disable.
                    return ResponseOutput.NotOk(_localizer["TrialSite_ParticipantJoined"]);
                }




            }
            else
            {
                if (await _trialSiteRepository.AnyAsync(t => t.Id != editTrialSiteCommand.Id && t.TrialSiteCode == editTrialSiteCommand.TrialSiteCode && t.TrialId == editTrialSiteCommand.TrialId))
                {
                    //---Code is not allowed to be repeated
                    return ResponseOutput.NotOk(_localizer["TrialSite_CodeDuplicate"]);
                }

                if (!string.IsNullOrEmpty(editTrialSiteCommand.TrialSiteCode) && await _trialRepository.AnyAsync(t => t.Id == trialId && t.VitrualSiteCode == editTrialSiteCommand.TrialSiteCode, true))
                {
                    return ResponseOutput.NotOk(_localizer["TrialSite_CodeDuplicate2"]);
                }
            }


            _mapper.Map(editTrialSiteCommand, dbEntity);

            if (editTrialSiteCommand.IsDeleted)
            {
                dbEntity.EnabledTime = null;

            }
            else if (editTrialSiteCommand.IsDeleted == false && dbEntity.EnabledTime == null)
            {
                dbEntity.EnabledTime = DateTime.Now;
            }

            await _trialSiteRepository.SaveChangesAsync();

            return ResponseOutput.Ok();

        }



        /// <summary> 批量添加Site下  CRC的负责人 </summary>
        [HttpPost]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task<IResponseOutput> AssignSiteCRC(List<AssginSiteCRCCommand> trialSiteCRCList)
        {
            var addArray = _mapper.Map<List<TrialSiteUser>>(trialSiteCRCList);

            await _trialSiteUserRepository.AddRangeAsync(addArray);

            await _trialSiteUserRepository.SaveChangesAsync();
            return ResponseOutput.Result(true);
        }

        /// <summary> 删除CRC人员</summary>
        [HttpDelete, Route("{id:guid}/{trialId:guid}/{isDelete:bool}")]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task<IResponseOutput> DeleteSiteCRC(Guid id, bool isDelete)
        {


            await _trialSiteUserRepository.UpdatePartialFromQueryAsync(t => t.Id == id, u => new TrialSiteUser() { IsDeleted = isDelete, DeletedTime = isDelete ? DateTime.Now : null }, true, true);

            //删除又启用改授权时间
            if (isDelete == false)
            {
                await _trialSiteUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new TrialSiteUser() { CreateTime = DateTime.Now });
            }

            ////不跟踪
            //await _trialSiteUserRepository.ExecuteUpdateAsync(t => t.Id == id, s=>s.SetProperty(t=>t.IsDeleted,u=>isDelete)
            //                                                                       .SetProperty(t=>t.DeletedTime,u=> isDelete ? DateTime.Now : null)
            //                                                                       .SetProperty(t=>t.CreateTime,u=>isDelete?u.CreateTime:DateTime.Now));




            return ResponseOutput.Ok();
        }

        /// <summary>
        ///   获取项目下的 site 下拉框数据    CRC只看到他负责的    
        /// </summary>
        /// <param name="trialId"></param>
        /// <returns></returns>
        [HttpGet("{trialId:guid}")]
        public async Task<IEnumerable<TrialSiteForSelect>> GetTrialSiteSelect(Guid trialId)
        {
            //CRC只看到他负责的    

            var list = await _trialSiteRepository.Where(t => t.TrialId == trialId)
                          .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.CRCUserList.Any(t => t.UserId == _userInfo.Id))
                          .ProjectTo<TrialSiteForSelect>(_mapper.ConfigurationProvider).OrderBy(t => t.TrialSiteCode).ToListAsync();


            return list;
        }



        public async Task<IEnumerable<string>> GetTrialSiteCodeSelect(Guid trialId, bool isIncludeVirtualSite = true)
        {
            //CRC只看到他负责的    

            var list = await _trialSiteRepository.Where(t => t.TrialId == trialId)
                          .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.CRCUserList.Any(t => t.UserId == _userInfo.Id))
                          .Select(t => t.TrialSiteCode).ToListAsync();

            var virtualList = await _visitTaskRepository.Where(t => t.IsSelfAnalysis == true && t.TrialId == trialId).Select(t => t.BlindTrialSiteCode).Distinct().ToListAsync();

            return isIncludeVirtualSite ? list.Concat(virtualList) : list;
        }


        /// <summary>删除  项目  下某一site </summary>
        [HttpDelete("{id:guid}/{trialId:guid}")]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        [Obsolete]
        public async Task<IResponseOutput> DeleteTrialSite(Guid id)
        {
            var relation = await _trialSiteRepository.FirstOrDefaultAsync(t => t.Id == id);

            if (relation == null) return Null404NotFound(relation);

            var trialId = relation.TrialId;
            var trialSiteId = relation.Id;

            if (await _trialSiteUserRepository.AnyAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId))
            {
                //---The site has been associated with CRC, and couldn't be deleted.
                return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedCRC"]);
            }

            if (await _subjectRepository.AnyAsync(t => t.TrialSiteId == trialSiteId && t.TrialId == trialId))
            {
                //---The subjects has been added to  this site, and couldn't be deleted.
                return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedSubject"]);
            }

            await _trialSiteRepository.DeleteAsync(relation);

            return ResponseOutput.Result(await _trialSiteUserRepository.SaveChangesAsync());
        }


    }
}
