using AutoMapper;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Performance.Services
{
    public class GuaranteeService : IAutoInjection
    {
        private readonly PerforPerallotRepository perforPerAllotRepository;
        private readonly PerforImdataRepository perforImdataRepository;
        private readonly PerforCofguaranteeRepository perforCofguaranteeRepository;
        public GuaranteeService(PerforPerallotRepository perforPerAllotRepository,
            PerforImdataRepository perforImdataRepository,
            PerforCofguaranteeRepository perforCofguaranteeRepository)
        {
            this.perforPerAllotRepository = perforPerAllotRepository;
            this.perforImdataRepository = perforImdataRepository;
            this.perforCofguaranteeRepository = perforCofguaranteeRepository;
        }


        #region cof_guarantee
        /// <summary>
        /// 保底绩效配置列表
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        public List<cof_guarantee> Guarantee(int allotId)
        {
            var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == allotId);
            return list?.OrderBy(t => t.Priority).ThenBy(t => t.Target).ToList();
        }

        /// <summary>
        /// 保底绩效配置列表
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        public List<GuaranteeResponse> GuaranTree(int allotId)
        {
            var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == allotId);
            if (list != null && list.Any())
            {
                var group = list
                    .Where(t => !string.IsNullOrEmpty(t.Target) && !string.IsNullOrEmpty(t.Source))
                    .GroupBy(t => new { t.UnitType, t.Target })
                    .Select(g => new GuaranteeResponse
                    {
                        AllotId = allotId,
                        Target = g.Key.Target,
                        Source = g.Select(t => new GuaranItems { GId = t.Id, GValue = t.Source }).ToList(),
                        Priority = g.Min(m => m.Priority.Value),
                        UnitType = g.Key.UnitType
                    }).OrderBy(t => t.UnitType).ThenBy(t => t.Priority).ToList();
                return group;
            }
            return new List<GuaranteeResponse>();
        }

        /// <summary>
        /// 新增保底绩效配置
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<cof_guarantee> GuarantInsert(GuaranteeRequest request)
        {
            var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == request.AllotId && t.UnitType == request.UnitType);
            if (list != null)
            {
                var config = list.FirstOrDefault(t => t.Priority == request.Priority);
                if (list.FirstOrDefault(t => t.Priority == request.Priority) != null || list.FirstOrDefault(t => t.Target == request.Target) != null)
                    throw new PerformanceException($"[{((UnitType)request.UnitType).ToString()}]已存在优先级\"{config.Target}({request.Priority})\",请重新选择");
                config = list.FirstOrDefault(t => t.Target == request.Target);
                if (config != null)
                    throw new PerformanceException($"[{((UnitType)request.UnitType).ToString()}]已存在优先级\"{request.Target}({config.Priority})\",请重新选择");
            }
            var guaranteeList = new List<cof_guarantee>();
            guaranteeList.AddRange(request.Source.Select(t => new cof_guarantee { Source = t.GValue }));
            guaranteeList.ForEach(t =>
            {
                t.AllotId = request.AllotId;
                t.Priority = request.Priority;
                t.UnitType = request.UnitType;
                t.Target = request.Target;
            });

            perforCofguaranteeRepository.AddRange(guaranteeList.ToArray());
            return guaranteeList;
        }

        /// <summary>
        /// 修改保底绩效配置
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<cof_guarantee> GuarantUpdate(GuaranteeRequest request)
        {
            var guarantee = perforCofguaranteeRepository.GetEntity(t => t.Id == request.Source.FirstOrDefault().GId);
            var guaranteeList = perforCofguaranteeRepository.GetEntities(t => t.AllotId == guarantee.AllotId && t.UnitType == guarantee.UnitType && t.Target == guarantee.Target);
            if (guaranteeList == null)
                throw new PerformanceException("提交数据无效");
            var filterList = perforCofguaranteeRepository.GetEntities(t => t.AllotId == guarantee.AllotId && t.UnitType == request.UnitType && t.Target == request.Target);
            if (request.UnitType != guarantee.UnitType && filterList != null && filterList.Count > 0)
                throw new PerformanceException($"[{((UnitType)request.UnitType).ToString()}]已存在\"{request.Target}\",请重新选择");

            #region 修改优先级
            if (request.AllotId == guarantee.AllotId && request.Target == guarantee.Target && request.UnitType == guarantee.UnitType && request.Priority != guarantee.Priority)
            {
                int flag = guaranteeList.FirstOrDefault().Priority.Value;
                if (flag > request.Priority)
                {
                    var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == request.AllotId && t.UnitType == request.UnitType && t.Priority >= request.Priority && t.Priority < flag);
                    if (list != null && list.Any())
                    {
                        list?.ForEach(t => { t.Priority = t.Priority + 1; });
                        perforCofguaranteeRepository.UpdateRange(list.ToArray());
                    }
                }
                else if (flag < request.Priority)
                {
                    var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == request.AllotId && t.UnitType == request.UnitType && t.Priority <= request.Priority && t.Priority > flag);
                    if (list != null && list.Any())
                    {
                        list.ForEach(t => { t.Priority = t.Priority - 1; });
                        perforCofguaranteeRepository.UpdateRange(list.ToArray());
                    }
                }
                else if (flag == request.Priority)
                {
                    if (filterList != null && filterList.Any())
                    {
                        filterList?.ForEach(t => { t.Priority = t.Priority + 1; });
                        perforCofguaranteeRepository.UpdateRange(filterList.ToArray());
                    }
                }
            }
            else
            {
                if (filterList != null && filterList.Any())
                {
                    filterList?.ForEach(t => { t.Priority = request.Priority; });
                    perforCofguaranteeRepository.UpdateRange(filterList.ToArray());
                }
            }
            #endregion

            #region 添加
            var insertList = request.Source.Where(t => t.GId.HasValue && t.GId == 0).Select(t => new cof_guarantee { Source = t.GValue }).ToList();
            insertList.ForEach(t =>
            {
                t.AllotId = request.AllotId;
                t.Priority = request.Priority;
                t.UnitType = request.UnitType;
                t.Target = request.Target;
            });
            perforCofguaranteeRepository.AddRange(insertList.ToArray());
            #endregion

            #region 修改、删除
            var delItem = new List<int>();
            var exist = request.Source.Where(t => t.GId.HasValue && t.GId != 0).Select(t => t.GId);
            guaranteeList.ForEach(t =>
            {
                if (exist.Contains(t.Id) && filterList.Select(s => s.Source).Contains(t.Source))
                    t.Source = request.Source.FirstOrDefault(s => s.GId == t.Id).GValue;
                else
                    delItem.Add(t.Id);
                t.Priority = request.Priority;
                t.UnitType = request.UnitType;
                t.Target = request.Target;
            });

            if (!perforCofguaranteeRepository.UpdateRange(guaranteeList.ToArray()))
                throw new PerformanceException("保存失败");

            if (delItem != null && delItem.Count() > 0)
                perforCofguaranteeRepository.RemoveRange(guaranteeList.Where(t => delItem.Contains(t.Id)).ToArray());
            #endregion

            guaranteeList.AddRange(insertList);
            return guaranteeList.Where(t => !delItem.Contains(t.Id))?.ToList();
        }

        /// <summary>
        /// 删除保底绩效配置
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        public bool GuarantDelete(GuaranteeRequest request)
        {
            var list = perforCofguaranteeRepository.GetEntities(t => t.AllotId == request.AllotId && t.UnitType == request.UnitType && t.Target == request.Target && t.Priority == request.Priority);
            if (list == null)
                return false;
            return perforCofguaranteeRepository.RemoveRange(list.ToArray());
        }

        /// <summary>
        /// 医院核算单元
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        public List<TitleValue> Accounting(int allotId)
        {
            List<TitleValue> result = new List<TitleValue>();
            var allot = perforPerAllotRepository.GetEntity(t => t.ID == allotId);
            if (allot == null)
                return result;
            var allotIds = perforPerAllotRepository.GetEntities(t => t.HospitalId == allot.HospitalId).Select(t => t.ID);
            var data = perforImdataRepository.GetEntities(t => allotIds.Contains(t.AllotID.Value))?.Select(t => t.AccountingUnit);
            if (data != null && data.Any())
            {
                data = data.Distinct().Where(t => !string.IsNullOrEmpty(t)).OrderBy(t => t).ToList();
                result.AddRange(data.Select(t => new TitleValue { Title = t, Value = t }));
            }
            return result;
        }
        #endregion

        /// <summary>
        /// 医院核算单元
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        public List<EnumItem> UnitType()
        {
            return UnitTypeUtil.GetUnitTypeFromEnum();
        }
    }
}
