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

namespace Performance.Services
{
    public class ReportService : IAutoInjection
    {
        private PerforReportRepository perforReportRepository;
        private PerforPerallotRepository perforPerallotRepository;
        private PerforResbaiscnormRepository perforResbaiscnormRepository;
        private PerforHospersonfeeRepository perforHospersonfeeRepository;
        private PerforResaccountRepository perforResaccountRepository;
        //private PerforResaccountnurseRepository perforResaccountnurseRepository;

        public ReportService(PerforReportRepository perforReportRepository,
            PerforPerallotRepository perforPerallotRepository,
            PerforResbaiscnormRepository perforResbaiscnormRepository,
            PerforHospersonfeeRepository perforHospersonfeeRepository,
            //PerforResaccountdoctorRepository perforResaccountdoctorRepository,
            PerforResaccountRepository perforResaccountRepository)
        {
            this.perforReportRepository = perforReportRepository;
            this.perforPerallotRepository = perforPerallotRepository;
            this.perforResbaiscnormRepository = perforResbaiscnormRepository;
            this.perforHospersonfeeRepository = perforHospersonfeeRepository;
            this.perforResaccountRepository = perforResaccountRepository;
            //this.perforResaccountnurseRepository = perforResaccountnurseRepository;
        }

        /// <summary>
        /// 月群体人均绩效
        /// </summary>
        /// <returns></returns>
        public List<PerReport> GetAvgPerfor(int hospitalid)
        {
            return perforReportRepository.GetAvgPerfor(hospitalid);
        }
        /// <summary>
        /// 人群绩效比
        /// </summary>
        /// <returns></returns>
        public List<PerReport> AvgRatio(int hospitalid)
        {
            return perforReportRepository.AvgRatio(hospitalid);
        }

        /// <summary>
        /// 首页数据概况
        /// </summary>
        /// <param name="request"></param>
        public dynamic Survey(int hospitalId)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var allot = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).FirstOrDefault();
            var keyvalue = new Dictionary<string, decimal>();
            var basicList = perforResbaiscnormRepository.GetEntities(t => t.AllotID == allot.ID);
            if (basicList != null)
            {
                foreach (var basic in basicList)
                {
                    keyvalue.Add(basic.PositionName, Math.Round(basic.AvgValue.Value, 2));
                }
            }
            var fee = perforHospersonfeeRepository.GetEntities(t => t.Year == allot.Year && t.Month == allot.Month);
            if (fee != null)
            {
                keyvalue.Add("门诊患者均次", Math.Round(fee.Where(t => t.Source == "门诊").Sum(t => t.Fee.Value) / fee.Where(t => t.Source == "门诊").Sum(t => t.PersonTime.Value), 2));
                keyvalue.Add("住院患者均次", Math.Round(fee.Where(t => t.Source == "住院").Sum(t => t.Fee.Value) / fee.Where(t => t.Source == "住院").Sum(t => t.PersonTime.Value), 2));
            }
            else
            {
                keyvalue.Add("门诊患者均次", 0M);
                keyvalue.Add("住院患者均次", 0M);
            }
            return new
            {
                year = allot.Year,
                month = allot.Month,
                avgperfor = keyvalue
            };
        }

        /// <summary>
        /// 科室医生人均绩效（含科主任）
        /// </summary>
        /// <returns></returns>
        public List<PerReport> DoctorAvg(int hospitalId, int isIndex)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var result = new List<PerReport>();
            var doctorList = perforResaccountRepository.GetEntities(t => t.UnitType != (int)UnitType.护理组 && allotList.Select(a => a.ID).Contains(t.AllotID.Value));
            if (isIndex == 1)
            {
                var allot = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).FirstOrDefault();
                doctorList = perforResaccountRepository.GetEntities(t => t.UnitType != (int)UnitType.护理组 && t.AllotID == allot.ID);
            }
            if (doctorList == null)
                return result;
            var s = from a in allotList
                    join d in doctorList on a.ID equals d.AllotID into data
                    from t in data
                    select new PerReport
                    {
                        Y = a.Year + "-" + a.Month.ToString().PadLeft(2, '0'),
                        X = t.AccountingUnit,
                        Value = Math.Round(t.Avg.Value, 2)
                    };
            return s.OrderBy(t => t.Y).ThenByDescending(t => t.Value).ToList();
        }

        /// <summary>
        /// 科室医生人均绩效（含科主任）
        /// </summary>
        /// <returns></returns>
        public List<PerReport> NurseAvg(int hospitalId, int isIndex)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var result = new List<PerReport>();
            var doctorList = perforResaccountRepository.GetEntities(t => t.UnitType == (int)UnitType.护理组 && allotList.Select(a => a.ID).Contains(t.AllotID.Value));
            if (isIndex == 1)
            {
                var allot = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).FirstOrDefault();
                doctorList = perforResaccountRepository.GetEntities(t => t.UnitType == (int)UnitType.护理组 && t.AllotID == allot.ID);
            }
            if (doctorList == null)
                return result;
            var s = from a in allotList
                    join d in doctorList on a.ID equals d.AllotID into data
                    from t in data
                    select new PerReport
                    {
                        Y = a.Year + "-" + a.Month.ToString().PadLeft(2, '0'),
                        X = t.AccountingUnit,
                        Value = Math.Round(t.Avg.Value, 2)
                    };
            return s.OrderBy(t => t.Y).ThenByDescending(t => t.Value).ToList();
        }


        /// <summary>
        /// 门诊患者均次费用
        /// </summary>
        /// <returns></returns>
        public List<PerReport> OutFeeAvg(int hospitalId)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var date = new List<string>();
            date = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).Take(6).Select(t => t.Year + "-" + t.Month.ToString().PadLeft(2, '0')).ToList();
            return perforReportRepository.OutFeeAvg(hospitalId, date);
        }

        /// <summary>
        /// 住院患者均次费用
        /// </summary>
        /// <returns></returns>
        public List<PerReport> InpatFeeAvg(int hospitalId)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var date = new List<string>();
            date = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).Take(6).Select(t => t.Year + "-" + t.Month.ToString().PadLeft(2, '0')).ToList();
            return perforReportRepository.InpatFeeAvg(hospitalId, date);
        }

        /// <summary>
        /// 科室药占比
        /// </summary>
        /// <returns></returns>
        public List<PerReport> Medicine(int hospitalId, int isIndex)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var date = new List<string>();
            if (isIndex == 1)
            {
                var allot = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).FirstOrDefault();
                date.Add(allot.Year + "-" + allot.Month.ToString().PadLeft(2, '0'));
            }
            else
            {
                date = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).Take(6).Select(t => t.Year + "-" + t.Month.ToString().PadLeft(2, '0')).ToList();
            }
            return perforReportRepository.Medicine(hospitalId, date);
        }

        /// <summary>
        /// 科室有效收入占比
        /// </summary>
        /// <returns></returns>
        public List<PerReport> Income(int hospitalId, int isIndex)
        {
            var states = new List<int>() { 6, 8 };
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && states.Contains(t.States));
            if (allotList == null || !allotList.Any())
                throw new PerformanceException("用户未创建绩效！");

            var date = new List<string>();
            if (isIndex == 1)
            {
                var allot = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).FirstOrDefault();
                date.Add(allot.Year + "-" + allot.Month.ToString().PadLeft(2, '0'));
            }
            else
            {
                date = allotList.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).Take(6).Select(t => t.Year + "-" + t.Month.ToString().PadLeft(2, '0')).ToList();
            }
            return perforReportRepository.Income(hospitalId, date);
        }
    }
}
