using DistributionApi.IRepositories;
using MadRunFabric.Common;
using MadRunFabric.Common.Options;
using MadRunFabric.Model;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace DistributionApi.Repositories
{
    public class DistributionAppChartRepository : BaseRepository<Pro_Project_Info, string>, IDistributionAppChartRepository
    {
        protected readonly ILogger<BaseRepository<Pro_Project_Info, string>> _logger;
        protected readonly IMongoCollection<Distri_Goods_Type> _collection_distri_goods_type;
        protected readonly IMongoCollection<Distri_Goods> _collection_distri_goods;
        protected readonly IMongoCollection<Distri_Workorder> _collection_distri_workorder;
        protected readonly IMongoCollection<Sys_Building> _collection_sys_building;
        protected readonly IMongoCollection<Sys_Floor> _collection_sys_floor;
        protected readonly IMongoCollection<Sys_Role_Info> _collection_role_info;
        protected readonly IMongoCollection<Sys_User_Account> _collection_sys_user_account;
        protected readonly IMongoCollection<Sys_DictionaryValue> _collection_sys_dictionaryvalue;
        protected readonly IMongoCollection<Sys_News> _collection_sys_news;
        public DistributionAppChartRepository(IOptions<MongodbOptions> settings,
            ILogger<BaseRepository<Pro_Project_Info, string>> logger) : base(settings, logger)
        {
            _collection_distri_goods_type = _context.GetCollection<Distri_Goods_Type>();  //获取集合
            _collection_distri_goods = _context.GetCollection<Distri_Goods>();  //获取集合
            _collection_distri_workorder = _context.GetCollection<Distri_Workorder>();  //获取集合
            _collection_sys_building = _context.GetCollection<Sys_Building>();  //获取集合
            _collection_sys_floor = _context.GetCollection<Sys_Floor>();  //获取集合
            _collection_role_info = _context.GetCollection<Sys_Role_Info>();
            _collection_sys_user_account = _context.GetCollection<Sys_User_Account>();  //获取集合
            _collection_sys_dictionaryvalue = _context.GetCollection<Sys_DictionaryValue>();
            _collection_sys_news = _context.GetCollection<Sys_News>();
            _logger = logger;
        }

        /// <summary>
        /// 员工运送工作量 - 统计报表
        /// </summary>
        /// <param name="projectid">项目id</param>
        /// <param name="usercode">用户code</param>
        /// <param name="stime">开始时间</param>
        /// <param name="etime">结束时间</param>
        /// <param name="userinfo">用户项目及相关信息</param>
        /// <returns></returns>
        public object GetWorkOrderCount(string projectid, string stime, string etime, UserAccountInfoModel userinfo)
        {
            #region 表查询
            //用户
            var query_user = from user in _collection_sys_user_account.AsQueryable()
                             join r in _collection_role_info.AsQueryable() on user.role_id equals r.id into roleinfo
                             where user.delete_flag == false && user.type != 2
                             select new
                             {
                                 user.id,
                                 user.head_img,
                                 user.usercode,
                                 user.username,
                                 user.projectlist,
                                 projectid = user.projectlist != null && user.projectlist.Count() > 0 ? user.projectlist.First() : null,
                                 roleid = user.role_id,
                                 rolecode = roleinfo != null && roleinfo.Count() > 0 ? roleinfo.First().role_code : null
                             };

            //科室 - 楼栋
            var query_build = from build in _collection_sys_building.AsQueryable()
                              where build.isdelete == 0 //&& goodstype.parent_id == null
                              select build;
            //科室 - 楼层
            var query_floor = from floor in _collection_sys_floor.AsQueryable()
                              where floor.isdelete == 0
                              orderby floor.sortnum descending
                              select floor;         
            //物品
            var query_goods = from goods in _collection_distri_goods.AsQueryable()
                        where goods.isdelete == 0
                        select goods;

            //配送工单
            var query_wo = from wo in _collection_distri_workorder.AsQueryable()
                           where wo.isdelete == 0
                           select wo;
            #endregion

            #region 判断条件
            if (!string.IsNullOrEmpty(projectid))
            {
                query_user = query_user.Where(x => x.projectlist.Contains(projectid));
                query_build = query_build.Where(it => it.projectid == projectid);
                query_goods = query_goods.Where(it => it.projectid == projectid);
                query_wo = query_wo.Where(it => it.projectid == projectid);
            }
            if (userinfo.isallproject == 0)
            {
                //query_user = query_user.Where(x => x.projectlist.Contains(projectid));
                query_build = query_build.Where(it => userinfo.projectlist.Contains(it.projectid));
                query_goods = query_goods.Where(it => userinfo.projectlist.Contains(it.projectid));
                query_wo = query_wo.Where(it => userinfo.projectlist.Contains(it.projectid));
            }
            query_user = query_user.Where(it => it.rolecode == "SSY_DTG" || it.rolecode == "SSY_PSG");

            if (!string.IsNullOrEmpty(stime))
                query_wo = query_wo.Where(it => it.createtime >= DateTime.Parse(stime + " 00:00:00"));
            if (!string.IsNullOrEmpty(etime))
                query_wo = query_wo.Where(it => it.createtime <= DateTime.Parse(etime + " 23:59:59"));
            #endregion

            #region 统计计算
            //获取工单统计 - 已配送/未完成
            var list_Wo = query_wo.Where(it => (it.wostate == (int)EnumDistributionState.finish || it.wostate == (int)EnumDistributionState.evaluated)).ToList();
            int nofinish_num = query_wo.Where(it => (it.wostate < (int)EnumDistributionState.finish || it.wostate == (int)EnumDistributionState.backed)).Count();
            int finished_num = list_Wo.Count();

            //综合满意度
            string evaluate_rate = "";
            var list_Evaluate = list_Wo.Where(it => it.starnum > 0);
            int evaluate_all = list_Evaluate.Count();
            int evaluate = list_Evaluate.Where(x => x.starnum > 3).Count();
            if (evaluate_all > 0)
                evaluate_rate = Math.Round(((double)evaluate * 100 / evaluate_all), 2) + "";

            //各科室（楼层）下单数量
            int departmentwonum_all = 0;
            //string departmentwonum_rate = "";
            var buildids = query_build.Select(x => x.id).ToList();
            var list_Floor = query_floor.ToList().Where(x => buildids.Contains(x.buildid)).ToList();
            var list_dep = list_Floor.Select(p =>
            {
                var list_WoItem = list_Wo.Where(x => x.deliverylist.Count > 0 && x.deliverylist.ToList().FirstOrDefault().department_name == p.remark).ToList();
                int departmentwonum = list_WoItem.Count();
                //departmentwonum_all += departmentwonum;
                return new
                {
                    p.id,
                    p.floorname,
                    departmentname = p.remark,
                    departmentwonum,
                    departmentwonum_rate = ""
                };
            });
            departmentwonum_all = list_dep.Sum(x => x.departmentwonum);
            if (departmentwonum_all > 0)
            {
                list_dep = list_dep.ToList().Select(p => 
                {
                    string dep_rate = Math.Round(((double)p.departmentwonum * 100 / departmentwonum_all), 2) + "";
                    return new
                    {
                        p.id,
                        p.floorname,
                        departmentname = p.departmentname,
                        p.departmentwonum,
                        departmentwonum_rate = dep_rate
                    };
                }).OrderByDescending(x => x.departmentwonum);
            }


            //配送物品排行
            int goodswonum_all = 0;
            var list_good = query_goods.ToList();
            var list_goods = list_good.Select(p =>
             {
                 var list_WoItem = list_Wo.Where(x => x.goodslist.Count > 0 && x.goodslist.ToList().FirstOrDefault().goodsid == p.id).ToList();
                 int goodswonum = list_WoItem.Count();
                 //goodswonum_all += goodswonum;
                 return new
                 {
                     p.id,
                     p.goodsname,
                     goodswonum,
                     goodswonum_rate = ""
                 };
             });
            goodswonum_all = list_goods.Sum(x => x.goodswonum);
            if (goodswonum_all > 0)
            {
                list_goods = list_goods.Select(p =>
                {
                    string goods_rate = Math.Round(((double)p.goodswonum * 100 / goodswonum_all), 2) + "";
                    return new
                    {
                        p.id,
                        p.goodsname,
                        p.goodswonum,
                        goodswonum_rate = goods_rate
                    };
                }).OrderByDescending(p => p.goodswonum);
            }

            //配送工单量排行
            var list_user = query_user.ToList().Select(p =>
             {
                 var list_WoItem = list_Wo.Where(x => (x.wostate == (int)EnumDistributionState.finish || x.wostate == (int)EnumDistributionState.evaluated) && (x.touser.Contains(p.usercode) || x.touser_elevator == p.usercode)).ToList();
                 int userwonum = list_WoItem.Count();
                 return new
                 {
                     p.id,
                     p.usercode,
                     p.username,
                     p.head_img,
                     userwonum
                 };
             }).OrderByDescending(p => p.userwonum);
            #endregion

            var obj = new
            {
                workordernum = new { nofinish_num, finished_num },
                evaluatenum = new { evaluate, evaluate_all, evaluate_rate},   //综合满意度
                list_dep = list_dep,                            //各科室下单数量
                list_goods = list_goods,                        //配送物品排行
                list_user = list_user                           //配送工单量排行
            };
            return obj;
        }

        #region 公示系统
        /// <summary>
        /// 各科室下单数量
        /// </summary>
        /// <param name="projectid">项目id</param>
        /// <param name="usercode">用户code</param>
        /// <param name="stime">开始时间</param>
        /// <param name="etime">结束时间</param>
        /// <param name="userinfo">用户项目及相关信息</param>
        /// <returns></returns>
        public object GetDepartmentWOCount(string projectid, string stime, string etime, UserAccountInfoModel userinfo)
        {
            #region 表查询
            //科室 - 楼栋
            var query_build = from build in _collection_sys_building.AsQueryable()
                              where build.isdelete == 0 //&& goodstype.parent_id == null
                              select build;
            //科室 - 楼层
            var query_floor = from floor in _collection_sys_floor.AsQueryable()
                              where floor.isdelete == 0
                              orderby floor.sortnum descending
                              select floor;         

            //配送工单
            var query_wo = from wo in _collection_distri_workorder.AsQueryable()
                           where wo.isdelete == 0
                           select wo;
            #endregion

            #region 判断条件
            if (!string.IsNullOrEmpty(projectid))
            {
                query_build = query_build.Where(it => it.projectid == projectid);
                query_wo = query_wo.Where(it => it.projectid == projectid);
            }
            if (userinfo.isallproject == 0)
            {
                query_build = query_build.Where(it => userinfo.projectlist.Contains(it.projectid));
                query_wo = query_wo.Where(it => userinfo.projectlist.Contains(it.projectid));
            }

            if (!string.IsNullOrEmpty(stime))
                query_wo = query_wo.Where(it => it.createtime >= DateTime.Parse(stime + " 00:00:00"));
            if (!string.IsNullOrEmpty(etime))
                query_wo = query_wo.Where(it => it.createtime <= DateTime.Parse(etime + " 23:59:59"));
            #endregion

            #region 统计计算
            //获取工单统计 - 完结
            var list_Wo = query_wo.Where(x => x.wostate == (int)EnumDistributionState.finish || x.wostate == (int)EnumDistributionState.evaluated).ToList();
            
            //各科室（楼层）下单数量
            int departmentwonum_all = 0;
            var buildids = query_build.Select(x => x.id).ToList();
            var list_Floor = query_floor.ToList().Where(x => buildids.Contains(x.buildid)).ToList();
            var list_dep = list_Floor.Select(p =>
            {
                var list_WoItem = list_Wo.Where(x => x.deliverylist.Count > 0 && x.deliverylist.ToList().FirstOrDefault().department_name == p.remark).ToList();
                int departmentwonum = list_WoItem.Count();
                return new
                {
                    p.id,
                    p.floorname,
                    departmentname = p.remark,
                    departmentwonum,
                    departmentwonum_rate = ""
                };
            });
            departmentwonum_all = list_dep.Sum(x => x.departmentwonum);
            if (departmentwonum_all > 0)
            {
                list_dep = list_dep.ToList().Select(p => 
                {
                    string dep_rate = Math.Round(((double)p.departmentwonum * 100 / departmentwonum_all), 2) + "";
                    return new
                    {
                        p.id,
                        p.floorname,
                        departmentname = p.departmentname,
                        p.departmentwonum,
                        departmentwonum_rate = dep_rate
                    };
                });
            }
            
            #endregion

            var obj = new
            {
                list_dep                      //配送工单量排行
            };
            return obj;
        }

        /// <summary>
        /// 配送物品前五
        /// </summary>
        /// <param name="projectid">项目id</param>
        /// <param name="usercode">用户code</param>
        /// <param name="stime">开始时间</param>
        /// <param name="etime">结束时间</param>
        /// <param name="userinfo">用户项目及相关信息</param>
        /// <returns></returns>
        public object GetGoodsWOCount(string projectid, string stime, string etime, UserAccountInfoModel userinfo)
        {
            #region 表查询   
            //物品
            var query_goods = from goods in _collection_distri_goods.AsQueryable()
                        where goods.isdelete == 0
                        select goods;

            //配送工单
            var query_wo = from wo in _collection_distri_workorder.AsQueryable()
                           where wo.isdelete == 0
                           select wo;
            #endregion

            #region 判断条件
            if (!string.IsNullOrEmpty(projectid))
            {
                query_goods = query_goods.Where(it => it.projectid == projectid);
                query_wo = query_wo.Where(it => it.projectid == projectid);
            }
            if (userinfo.isallproject == 0)
            {
                query_goods = query_goods.Where(it => userinfo.projectlist.Contains(it.projectid));
                query_wo = query_wo.Where(it => userinfo.projectlist.Contains(it.projectid));            }

            if (!string.IsNullOrEmpty(stime))
                query_wo = query_wo.Where(it => it.createtime >= DateTime.Parse(stime + " 00:00:00"));
            if (!string.IsNullOrEmpty(etime))
                query_wo = query_wo.Where(it => it.createtime <= DateTime.Parse(etime + " 23:59:59"));
            #endregion

            #region 统计计算
            //获取工单统计 - 完结
            var list_Wo = query_wo.Where(x => x.wostate == (int)EnumDistributionState.finish || x.wostate == (int)EnumDistributionState.evaluated).ToList();

            //配送物品排行
            int goodswonum_all = 0;
            var list_good = query_goods.ToList();
            var list_goods = list_good.Select(p =>
             {
                 var list_WoItem = list_Wo.Where(x => x.goodslist.Count > 0 && x.goodslist.ToList().FirstOrDefault().goodsid == p.id).ToList();
                 int goodswonum = list_WoItem.Count();
                 return new
                 {
                     p.id,
                     p.goodsname,
                     goodswonum,
                     goodswonum_rate = ""
                 };
             });
            goodswonum_all = list_goods.Sum(x => x.goodswonum);
            if (goodswonum_all > 0)
            {
                list_goods = list_goods.Select(p =>
                {
                    string goods_rate = Math.Round(((double)p.goodswonum * 100 / goodswonum_all), 2) + "";
                    return new
                    {
                        p.id,
                        p.goodsname,
                        p.goodswonum,
                        goodswonum_rate = goods_rate
                    };
                }).OrderByDescending(p => p.goodswonum);
            }
            #endregion

            var obj = new
            {
                list_goods                        //配送物品排行
            };
            return obj;
        }
        
        #endregion

    }
}
