using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infra.EFCore.Common;
using MassTransit;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Contracts;

namespace IRaCIS.Core.Application.Service
{	
	/// <summary>
	/// 医学审核问题
	/// </summary>	
	[ ApiExplorerSettings(GroupName = "Reading")]
	public class ReadingMedicineQuestionService: BaseService, IReadingMedicineQuestionService
	{

	    private readonly IRepository<ReadingMedicineTrialQuestion> _readingMedicineTrialQuestionRepository;
        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<ReadingMedicineSystemQuestion> _readingMedicineSystemQuestionRepository;

        public ReadingMedicineQuestionService(
			IRepository<ReadingMedicineTrialQuestion> readingMedicineTrialQuestionRepository,
			IRepository<Trial> trialRepository,
			IRepository<ReadingMedicineSystemQuestion> readingMedicineSystemQuestionRepository
			)
		{
            this._readingMedicineTrialQuestionRepository = readingMedicineTrialQuestionRepository;
            this._trialRepository = trialRepository;
            this._readingMedicineSystemQuestionRepository = readingMedicineSystemQuestionRepository;
        }


		/// <summary>
		/// 获取系统的医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<List<ReadingMedicineSystemQuestionView>> GetReadingMedicineSystemQuestionList(ReadingMedicineSystemQuestionQuery inDto)
		{
			var query = _readingMedicineSystemQuestionRepository.AsQueryable()
				  .WhereIf(!inDto.TypeValue.IsNullOrEmpty(), x => x.TypeValue.Contains(inDto.TypeValue))
				  .WhereIf(!inDto.ParentTriggerValue.IsNullOrEmpty(), x => x.ParentTriggerValue.Contains(inDto.ParentTriggerValue))
				  .WhereIf(!inDto.QuestionName.IsNullOrEmpty(), x => x.QuestionName.Contains(inDto.QuestionName))
				  .WhereIf(!inDto.Type.IsNullOrEmpty(), x => x.Type.Contains(inDto.Type))
				  .ProjectTo<ReadingMedicineSystemQuestionView>(_mapper.ConfigurationProvider).OrderBy(x=>x.ShowOrder);
			return await query.ToListAsync();
		}

		/// <summary>
		/// 新增或修改系统医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<IResponseOutput> AddOrUpdateReadingMedicineSystemQuestion(ReadingMedicineSystemQuestionAddOrEdit inDto)
		{
			var existsQuery = _readingMedicineSystemQuestionRepository
			   .WhereIf(inDto.Id != null, x => x.Id != inDto.Id)
			   .Where(x => x.QuestionName == inDto.QuestionName ||x.ShowOrder == inDto.ShowOrder);

			if (await existsQuery.AnyAsync())
			{
				return ResponseOutput.NotOk("当前问题名称或序号存在重复");
			}
			var entity = await _readingMedicineSystemQuestionRepository.InsertOrUpdateAsync(inDto);
			await _readingMedicineSystemQuestionRepository.SaveChangesAsync();
			return ResponseOutput.Ok(entity.Id.ToString());
		}


		

		/// <summary>
		/// 删除系统的医学审核问题
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		[HttpDelete("{id:guid}")]
		public async Task<IResponseOutput> DeleteReadingMedicineSystemQuestion(Guid id)
		{
			if (await _readingMedicineSystemQuestionRepository.AnyAsync(x => x.ParentId == id))
			{
				return ResponseOutput.NotOk("此问题存在子问题,请先删除子问题");
			}
			var success = await _readingMedicineSystemQuestionRepository.DeleteFromQueryAsync(t => t.Id == id);
			var result = await _readingMedicineSystemQuestionRepository.SaveChangesAsync();
			return ResponseOutput.Result(result);
		}

		/// <summary>
		/// 获取项目的医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<(List<ReadingMedicineTrialQuestionView>,object)>  GetReadingMedicineTrialQuestionList(ReadingMedicineTrialQuestionQuery inDto)
		{
			var query = _readingMedicineTrialQuestionRepository.AsQueryable()
				   .Where(x=>x.TrialId==inDto.TrialId)
				   .WhereIf(!inDto.TypeValue.IsNullOrEmpty(), x => x.TypeValue.Contains(inDto.TypeValue))
				   .WhereIf(!inDto.ParentTriggerValue.IsNullOrEmpty(), x => x.ParentTriggerValue.Contains(inDto.ParentTriggerValue))
				   .WhereIf(!inDto.QuestionName.IsNullOrEmpty(), x => x.QuestionName.Contains(inDto.QuestionName))
				   .WhereIf(!inDto.Type.IsNullOrEmpty(), x => x.Type.Contains(inDto.Type))
				   .ProjectTo<ReadingMedicineTrialQuestionView>(_mapper.ConfigurationProvider).OrderBy(x=>x.ShowOrder);


			var isConfirmMedicineQuestion = await _trialRepository.Where(x => x.Id == inDto.TrialId).Select(x => x.IsConfirmMedicineQuestion).FirstOrDefaultAsync();
			var questionList = await query.ToListAsync();
			return (questionList, new {
				IsConfirmMedicineQuestion= isConfirmMedicineQuestion,
				QuestionCount= questionList.Count(),
			});
		}

		/// <summary>
		/// 获取预览问题信息
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<List<GetMedicineQuestionPreviewOutDto>> GetMedicineQuestionPreview(GetMedicineQuestionPreviewInDto inDto)
		{
			var trialQuestionList = await _readingMedicineTrialQuestionRepository.Where(x=>x.TrialId==inDto.TrialId)
				 .ProjectTo<GetMedicineQuestionPreviewOutDto>(_mapper.ConfigurationProvider).OrderBy(x=>x.ShowOrder).ToListAsync();
		
			List<GetMedicineQuestionPreviewOutDto> readingQuestionList = trialQuestionList.Where(x => x.ParentId == null).ToList();
			readingQuestionList.ForEach(x =>
			{
				FindChildQuestion(x, trialQuestionList);
			});

			return readingQuestionList;
		}

		private void FindChildQuestion(GetMedicineQuestionPreviewOutDto trialReadingQuestion, List<GetMedicineQuestionPreviewOutDto> questionlists)
		{
			trialReadingQuestion.Childrens = questionlists.Where(x => x.ParentId == trialReadingQuestion.Id).ToList();
			if (trialReadingQuestion.Childrens != null && trialReadingQuestion.Childrens.Count != 0)
			{
				trialReadingQuestion.Childrens.ForEach(x =>
				{
					this.FindChildQuestion(x, questionlists);
				});
			}
		}

		/// <summary>
		/// 新增或修改项目医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async  Task<IResponseOutput> AddOrUpdateReadingMedicineTrialQuestion(ReadingMedicineTrialQuestionAddOrEdit inDto)
		{
			var existsQuery = _readingMedicineTrialQuestionRepository
		   .WhereIf(inDto.Id != null, x => x.Id != inDto.Id)
		   .Where(x => x.TrialId==inDto.TrialId)
		   .Where(x => x.QuestionName == inDto.QuestionName || x.ShowOrder == inDto.ShowOrder);

			if (await existsQuery.AnyAsync())
			{
				return ResponseOutput.NotOk("当前问题名称或序号存在重复");
			}
			var entity = await _readingMedicineTrialQuestionRepository.InsertOrUpdateAsync(inDto);
			await _readingMedicineTrialQuestionRepository.SaveChangesAsync();
			return ResponseOutput.Ok(entity.Id.ToString());

		}

		/// <summary>
		/// 获取项目的其他医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<List<GetReadingMedicineTrialOtherQuestionOutDto>> GetReadingMedicineTrialOtherQuestion(GetReadingMedicineTrialOtherQuestionInDto inDto)
		{
			var types = new List<string>()
			{
				"select","radio"
			};

			var questionList = await _readingMedicineTrialQuestionRepository.Where(x => x.TrialId == inDto.TrialId)
				.Where(x => types.Contains(x.Type))
				.WhereIf(inDto.Id != null, x => x.Id != inDto.Id && x.ParentId != inDto.Id)
				.WhereIf(inDto.ShowOrder != null, x => x.ShowOrder <inDto.ShowOrder)
				.Select(x => new GetReadingMedicineTrialOtherQuestionOutDto()
				{
					Id = x.Id,
					QuestionName = x.QuestionName,
					TypeValue=x.TypeValue,

				}).ToListAsync();

			return questionList;
		}

		/// <summary>
		/// 从系统里面选择问题添加到项目里面
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
		public async Task<IResponseOutput> AddTrialDataFromSystem(AddTrialDataFromSystemInDto inDto)
		{
			// 直接写??
			var systemList = await _readingMedicineSystemQuestionRepository.Where(x => inDto.SystemQuestionIds.Contains(x.Id)).ToListAsync();
			var needList= systemList.Select(x => new ReadingMedicineTrialQuestion()
				{
					Id = NewId.NextGuid(),
					ShowOrder = x.ShowOrder,
					IsEnable = x.IsEnable,
					IsRequired = x.IsRequired,
					QuestionName = x.QuestionName,
					Type = x.Type,
					TypeValue = x.TypeValue,
					TrialId=inDto.TrialId,
				}).ToList();

			 await _readingMedicineTrialQuestionRepository.AddRangeAsync(needList);
			 var result = await _readingMedicineTrialQuestionRepository.SaveChangesAsync();
			 return ResponseOutput.Result(result);
		}

		/// <summary>
		/// 删除项目的医学审核问题
		/// </summary>
		/// <param name="inDto"></param>
		/// <returns></returns>
		[HttpPost]
        public async Task<IResponseOutput> DeleteReadingMedicineTrialQuestion(DeleteReadingMedicineTrialQuestion inDto)
		{
			if (await _readingMedicineTrialQuestionRepository.AnyAsync(x => x.ParentId == inDto.Id))
			{
				return ResponseOutput.NotOk("此问题存在子问题,请先删除子问题");
			}
			var success = await _readingMedicineTrialQuestionRepository.DeleteFromQueryAsync(t => t.Id == inDto.Id);
			var result = await _readingMedicineTrialQuestionRepository.SaveChangesAsync();
			return ResponseOutput.Result(result);
		}


        /// <summary>
        /// 确认医学审核问题
        /// </summary>
        /// <returns></returns>
        public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(ConfirmReadingMedicineQuestionInDto inDto)
        {
			var readingMedicineQuestionList = await _readingMedicineTrialQuestionRepository.Where(x => x.TrialId == inDto.TrialId)
				.Select(x => new TrialQuestion() {
					Id = x.Id,
					ParentShowOrder = (int?)x.ParentQuestion.ShowOrder,
					ShowOrder=x.ShowOrder,
				}).ToListAsync();					
			if (readingMedicineQuestionList.Count == 0)
			{
				throw new BusinessValidationFailedException("当前未添加医学审核问题。请先添加医学审核问题,再进行确认。");
			}

			if (readingMedicineQuestionList.Count() != readingMedicineQuestionList.Select(t => t.ShowOrder).Distinct().Count())
			{
				throw new BusinessValidationFailedException("影像医学审核问题显示序号不能重复。");
			}


			if (readingMedicineQuestionList.Where(t => t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder))
			{
				throw new BusinessValidationFailedException("父问题的显示序号要比子问题的显示序号小,请确认。");
			}


			await _readingMedicineTrialQuestionRepository.BatchUpdateNoTrackingAsync(x => x.TrialId == inDto.TrialId, x => new ReadingMedicineTrialQuestion()
			{
				IsConfirm = true
			});

			await _trialRepository.UpdatePartialFromQueryAsync(inDto.TrialId, x => new Trial()
			{
				IsConfirmMedicineQuestion = true
			});

			var result = await _trialRepository.SaveChangesAsync();
			return ResponseOutput.Result(result);



		}



    }
}