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

namespace Performance.Services
{
    /// <summary>
    /// 工作量
    /// </summary>
    public class PerSheetDataComputeWorkload : IAutoInjection
    {
        #region 工作量一次计算
        /// <summary>
        /// 工作量一次计算
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="confs">药占比分值</param>
        /// <returns></returns>
        public PerSheet OnceCompute(PerSheet sheet, List<CofDrugProp> confs = null)
        {
            var dataList = sheet.PerData.Select(t => (PerData)t);
            int phead = 0;
            //修改cell坐标，为新增合计预留位置
            foreach (var header in sheet.PerHeader)
            {
                if (header.IsHasChildren)
                {
                    header.PointCell = header.PointCell + phead;
                    header.MergeCell = header.MergeCell + 1;
                    header.Children.ForEach(item => item.PointCell = item.PointCell + phead);
                    phead = phead + 1;
                }
            }

            Dictionary<string, PerHeader> perHead = new Dictionary<string, PerHeader>();
            List<PerData> perDataList = new List<PerData>();
            //插入合计结果
            foreach (var header in sheet.PerHeader)
            {
                if (header.IsHasChildren)
                {
                    var maxcell = header.Children.Max(t => t.PointCell);
                    var parentHead = new PerHeader(1, maxcell + 1, $" {header.CellValue}合计", 0, 1, 1, new List<PerHeader>(), 1);
                    perHead.Add(header.SignID, parentHead);

                    var typeClass = dataList.Where(t => header.Children.Select(s => s.CellValue).Contains(t.TypeName));
                    int pointcell = 0;

                    foreach (var group in typeClass.GroupBy(t => t.UnitType))
                    {
                        var ds = group.Where(t => t.CellValue.HasValue)
                            .GroupBy(t => t.AccountingUnit).Select(t => new PerData
                            {
                                UnitType = group.Key,
                                AccountingUnit = t.Key,
                                CellValue = ComputValue(header, confs, t),
                                TypeName = group.Key,
                                RowNumber = t.FirstOrDefault()?.RowNumber ?? 0,
                                IsTotal = 1,
                                PointCell = maxcell + pointcell,
                                ComputRule = t.Select(s => s.ComputRule).Distinct().First(),
                                SignID = parentHead.SignID,
                            });
                        perDataList.AddRange(ds);
                    }
                }
            }
            foreach (var item in perHead.Keys)
            {
                sheet.PerHeader.FirstOrDefault(t => t.SignID == item)?.Children.Add(perHead[item]);
            }
            sheet.PerData.AddRange(perDataList);

            return sheet;
        }

        private decimal? ComputValue(PerHeader header, List<CofDrugProp> confs, IGrouping<string, PerData> group)
        {
            var value = group.Sum(s => s.IsFactor ? s.CellValue * s.FactorValue : s.CellValue);
            if (header.CellValue == "门急诊工作量")
            {
                var factor = confs.FirstOrDefault(t => t.AccoutingUnit == group.Key)?.Factor ?? 0;
                value = value * factor;
            }

            return value;
        }
        #endregion


        #region 工作量二次计算
        /// <summary>
        /// 工作量二次计算
        /// </summary>
        /// <param name="sheet"></param>
        /// <returns></returns>
        public (PerSheet Sheet, List<PerData> PerData) TwiceCompute(PerSheet sheet, List<CofDrugProp> confs = null, List<cof_workitem> workitems = null)
        {
            //获取最大列坐标位置
            int thiscell = sheet.PerHeader.OrderByDescending(t => t.PointCell).FirstOrDefault().PointCell + 1;
            PerHeader perHead = new PerHeader(0, thiscell, "工作量绩效合计", 0, 1, 1, new List<PerHeader>(), 1);

            var dataList = sheet.PerData.Select(t => (PerData)t);

            List<PerData> perDataList = new List<PerData>();
            //插入合计结果
            //var groupList = dataList.Where(t => t.IsTotal == 1 && t.CellValue.HasValue).GroupBy(t => new { t.UnitType, t.AccountingUnit });
            var groupList = dataList.Where(t => t.CellValue.HasValue).GroupBy(t => new { t.UnitType, t.AccountingUnit });
            foreach (var group in groupList)
            {
                var ds = group.Select(t => new PerData
                {
                    UnitType = group.Key.UnitType,
                    AccountingUnit = group.Key.AccountingUnit,
                    //CellValue = group.Sum(s => s.CellValue),
                    CellValue = ComputValue(group, confs, workitems),
                    TypeName = group.Key.UnitType,
                    RowNumber = group.FirstOrDefault()?.RowNumber ?? 0,
                    IsTotal = 1,
                    PointCell = thiscell,
                    ComputRule = group.Select(s => s.ComputRule).Distinct().First(),
                    SignID = perHead.SignID,
                });
                perDataList.AddRange(ds);
            }
            sheet.PerHeader.Add(perHead);
            sheet.PerData.AddRange(perDataList);
            return (sheet, perDataList);
        }

        private decimal? ComputValue(IGrouping<object, PerData> group, List<CofDrugProp> confs = null, List<cof_workitem> workitems = null)
        {
            if (confs == null || workitems == null)
                return group.Sum(s => s.IsFactor ? s.CellValue * s.FactorValue : s.CellValue);
            else
            {
                var factor = confs.FirstOrDefault(t => t.AccoutingUnit == group.First().AccountingUnit)?.Factor ?? 1;
                //需要乘系数的项
                var fgroup = group.Where(t => workitems.Select(s => s.Item).Contains(t.TypeName));
                //需要乘系数的项
                var ngroup = group.Where(t => !workitems.Select(s => s.Item).Contains(t.TypeName));

                var value = fgroup.Sum(s => s.IsFactor ? s.CellValue * s.FactorValue : s.CellValue) * factor;
                value += ngroup.Sum(s => s.IsFactor ? s.CellValue * s.FactorValue : s.CellValue);
                return value;
            }
        }
        #endregion
    }
}
