using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.KpiRespository.Repositories;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.QmsRepository;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.TpmRepository;
using System;
using System.Collections.Generic;
using System.Linq;
using Siger.Middlelayer.Log;
using TimeRange = Siger.Middlelayer.Share.Models.TimeRange;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository;
using Siger.Middlelayer.TpmRepository.Response;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.KpiRespository.Respose;
using Siger.Middlelayer.QmsRepository.Entities;
using SigerProjectKpiTasklist = Siger.Middlelayer.KpiRespository.Entities.SigerProjectKpiTasklist;
using Siger.Middlelayer.Repository.Response;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.KpiRespository;
using siger_check_sn_trace_inspection = Siger.Middlelayer.QmsRepository.Entities.siger_check_sn_trace_inspection;

namespace Siger.ApiDashboard.Tasks
{
    public class MonthReportHelper
    {
        private readonly ApiTpmDbContext _tpmDbContext;
        private readonly ApiQmsDbContext _qmsDbContext;
        private readonly ApiKpiDbContext _kpiDbContext;
        private readonly ApiConfigDbContext _configDbContext;
        private readonly ApiAccDbContext _accDbContext;
        public MonthReportHelper(ApiQmsDbContext qmsDbContext, ApiTpmDbContext tpmDbContext, ApiKpiDbContext kpiDbContext, ApiConfigDbContext configDbContext, ApiAccDbContext accDbContext)
        {
            _qmsDbContext = qmsDbContext;
            _configDbContext = configDbContext;
            _tpmDbContext = tpmDbContext;
            _kpiDbContext = kpiDbContext;
            _accDbContext = accDbContext;
        }
        /// <summary>
        /// 获取报表配置
        /// </summary>
        /// <returns></returns>
        public List<siger_project_monthreport_config> GetAllConfigs()
        {

            var configList = new List<siger_project_monthreport_config>();
            var configs = _configDbContext.siger_project_monthreport_config.Where(q => q.status == (int)RowState.Valid
                                                                               && q.first_date <= DateTime.Now && q.user_mids != "").ToList();
            //过滤发送时间
            foreach (var config in configs)
            {
                var success = DateTime.TryParse(DateTime.Now.ToShortDateString() + " " + config.send_time, out DateTime dt);
                if (success)
                {
                    var seconds = DateTime.Now.Subtract(dt).TotalSeconds;
                    if (seconds >= 0 && seconds < 300)
                    {
                        var needSend = IsNeedSendReport(config);
                        if (needSend)
                        {
                            configList.Add(config);
                        }
                    }
                }
            }
            return configList;
        }

        private bool IsNeedSendReport(siger_project_monthreport_config config)
        {
            if (config.cycle == MonthReportCycle.Day)
            {
                var dtStart = config.first_date.Date;
                var dtEnd = config.first_date.AddYears(1); //默认查一年的
                DateTime dtDay;
                var interval = config.day_interval.ToInt();
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddDays(interval).Date)
                {
                    if (dtDay.Date.Subtract(DateTime.Now.Date).TotalDays == 0)
                    {
                        return true;
                    }
                }
            }

            if (config.cycle == MonthReportCycle.Week)
            {
                if (!string.IsNullOrWhiteSpace(config.day_interval))
                {
                    var days = config.day_interval.Split(',').ToList();
                    var now = DateTime.Now.DayOfWeek;
                    foreach (var day in days)
                    {
                        if (day.ToInt() == (int)now)
                        {
                            return true;
                        }
                    }
                }
            }

            if (config.cycle == MonthReportCycle.Month)
            {
                if (config.day_interval == "1") //月初
                {
                    if (DateTime.Now.Day == 1)
                    {
                        return true;
                    }
                }
                else if (config.day_interval == "2") //月末
                {
                    if (DateTime.Today.AddDays(1) == DateTime.Parse(DateTime.Now.AddMonths(1).ToString("yyyy-MM-01")))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public SigerProjectEmailConfig GetEmailConfigs(int projectId)
        {
            return _configDbContext.siger_project_email_config.FirstOrDefault(q => q.project == projectId && q.status == (int)RowState.Valid);
        }
        public IEnumerable<siger_project_user> UserEmails(string userMids)
        {
            var userIds = userMids.Split(',').ToList();

            return _configDbContext.siger_project_user.Where(q =>
                userIds.Contains(q.mid.ToString()) && q.work_email != "" && q.status == (int)RowState.Valid).ToList();
        }
        public IEnumerable<siger_project_monthreport_config_template> GetRptTemplates(int typeId)
        {
            return _configDbContext.siger_project_monthreport_config_template.Where(f => f.parent_id == typeId);
        }

        public void AddSendRecord(int configId, string acceptUsers, string filePath)
        {
            try
            {
                var entity = new siger_project_monthreport_sendrecord
                {
                    config_id = configId,
                    send_time = DateTime.Now,
                    accept_mid = 0,
                    accept_usernames = acceptUsers,
                    file_path = filePath ?? "",
                    file_content = new byte[] { },
                    status = (int)RowState.Valid
                };
                _configDbContext.siger_project_monthreport_sendrecord.Add(entity);
                _configDbContext.SaveChanges();
            }
            catch (Exception e)
            {
                Logger.WriteLineError(e.ToString());
            }
        }
        public TimeRange TimeRange(siger_project_monthreport_config config)
        {
            var dtStrat = string.Empty;
            var dtEnd = string.Empty;
            if (config.cycle == MonthReportCycle.Day)
            {
                dtStrat = DateTime.Parse(DateTime.Now.AddDays(-config.day_interval.ToInt()).ToString(ParameterConstant.DateFormat) + " " + config.send_time).ToString(ParameterConstant.DateTimeFormat);

                dtEnd = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateFormat) + " " + config.send_time).ToString(ParameterConstant.DateTimeFormat);
            }

            if (config.cycle == MonthReportCycle.Week)
            {
                int interval = 7;
                var days = config.day_interval.Split(',');
                if (days.Length > 1)
                {
                    var dayofweek = DateTime.Now.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)DateTime.Now.DayOfWeek;
                    var listDays = new List<int>();
                    foreach (var day in days)
                    {
                        listDays.Add(day == "0" ? 7 : day.ToInt());
                    }

                    for (var i = 0; i < listDays.Count; i++) //从1到7
                    {
                        var day = listDays[i];
                        if (day == dayofweek)
                        {
                            if (i == 0)
                            {
                                interval = 7 - (listDays[listDays.Count - 1] - dayofweek);
                            }
                            else
                            {
                                interval = listDays[listDays.Count - 1] - listDays[i - 1];
                            }
                        }
                    }
                }

                dtStrat = DateTime.Parse(DateTime.Now.AddDays(-interval).ToString(ParameterConstant.DateFormat) + " " + config.send_time).ToString(ParameterConstant.DateTimeFormat);
                dtEnd = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.DateFormat) + " " + config.send_time).ToString(ParameterConstant.DateTimeFormat);
            }

            if (config.cycle == MonthReportCycle.Month)
            {
                if (config.day_interval == "1")
                {
                    dtStrat = DateTime.Now.AddMonths(-1).ToString(ParameterConstant.MouthFirstDay + ParameterConstant.TimeFromZero);
                    dtEnd = DateTime.Now.AddDays(-1).ToString(ParameterConstant.DateToEnd);

                    return new TimeRange(dtStrat.ToDateTime(), dtEnd.ToDateTime());
                }
                else
                {
                    dtStrat = DateTime.Parse(DateTime.Now.ToString(ParameterConstant.MouthFirstDay) + " " + config.send_time)
                        .ToString(ParameterConstant.DateTimeFormat);
                    dtEnd = DateTime.Parse(DateTime.Now.AddMonths(1).ToString(ParameterConstant.MouthFirstDay) + " " + config.send_time)
                        .AddSeconds(-1)
                        .ToString(ParameterConstant.DateTimeFormat);
                }
            }

            return new TimeRange(dtStrat.ToDateTime(), dtEnd.ToDateTime());
        }

        /// <summary>
        /// 通道/产线信息
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public IEnumerable<siger_project_level_section> GetAccLines(int projectId)
        {
            var linelevel = _configDbContext.siger_project_level.Where(f => f.projectid == projectId && f.status == (int)RowState.Valid).OrderByDescending(o => o.id).ToList();
            if (!linelevel.Any() || linelevel.Count < 2)
                return new List<siger_project_level_section>();
            var lineSetion = _configDbContext.siger_project_level_section.Where(f => f.projectid == projectId && f.levelid == linelevel[1].id && f.status == (int)RowState.Valid);
            return lineSetion;
        }
        public IEnumerable<int> GetLevelSectionIds(int id, int projectid)
        {
            var list = new List<int>();
            var query = GetSonLevelSections(id, projectid);

            list.Add(id);
            foreach (var section in query.ToList())
            {
                list.Add(section.id);
            }

            return list;
        }
        public IEnumerable<siger_project_level_section> GetSonLevelSections(int parentId, int projectid)
        {
            if (parentId == 0)
            {
                return GetAllSections(projectid);
            }

            var query = (from c in _configDbContext.siger_project_level_section
                         where c.id == parentId && c.projectid == projectid && c.status == (int)RowState.Valid
                         select c).FirstOrDefault();
            if (query != null && query.parentid == 0)
            {
                return GetAllSections(projectid);
            }

            return GetSonLevelSectionsLop(parentId, projectid);
        }
        private IEnumerable<siger_project_level_section> GetSonLevelSectionsLop(int parentId, int projectid)
        {
            var query = from c in _configDbContext.siger_project_level_section
                        where c.parentid == parentId && c.projectid == projectid && c.status == (int)RowState.Valid
                        select c;

            return query.ToList().Concat(query.ToList().SelectMany(t => GetSonLevelSectionsLop(t.id, projectid)));
        }
        private IEnumerable<siger_project_level_section> GetAllSections(int projectid)
        {
            return _configDbContext.siger_project_level_section.Where(q => q.projectid == projectid && q.status == (int)RowState.Valid).ToList();
        }
        /// <summary>
        /// 检验数据
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="stations"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IEnumerable<siger_check_sn_trace_material> GetTraceMaterial(int projectId, List<int> stations,DateTime begin,DateTime end)
        {
            var query = from m in _qmsDbContext.siger_check_sn_trace_material.Where(f => f.projectid == projectId && stations.Contains(f.SectionID) && f.CreateTime >= begin && f.CreateTime <= end)
                        select m;
            return query.AsNoTracking();

        }
        /// <summary>
        /// 送检数据
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="stations"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IEnumerable<siger_check_sn_trace_inspection>GetTraceInspection(int projectId,List<int>stations,DateTime begin,DateTime end)
        {
            var query = from m in _qmsDbContext.siger_check_sn_trace_inspection.Where(f => f.projectid == projectId && stations.Contains(f.sectionid) && f.send_time >= begin && f.send_time <= end)
                        select m;
            return query.AsNoTracking();
        }
        /// <summary>
        /// 返工报废数据
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="stations"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IEnumerable<siger_qms_rework_data>GetReworkDat(int projectId, List<int> stations, DateTime begin, DateTime end)
        {
            var query = from m in _qmsDbContext.siger_qms_rework_data.Where(f => f.projectid == projectId && stations.Contains(f.Section_Id) && f.DateTime >= begin && f.DateTime <= end)
                        select m;
            return query.AsNoTracking();
        }

        /// <summary>
        /// 安灯主表
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="stations"></param>
        /// <param name="beginTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public IEnumerable<siger_andon_info>GetAndonInfo(int projectId, List<int> stations, long beginTime, long endTime)
        {
            var query = from m in _qmsDbContext.siger_andon_info.Where(f => f.projectid == projectId && stations.Contains(f.station) && f.create_time >= beginTime && f.create_time <= endTime && f.status > (int)AndonState.Abnormal && f.status <= (int)AndonState.CancleAbnormal)
                        select m;
            return query.AsNoTracking();
        }

        public IEnumerable<SigerTrSnTrace>GetSnTrace(int projectId, List<int> stations, DateTime begin, DateTime end)
        {
            var query = from m in _accDbContext.siger_tr_sn_trace.Where(f => f.projectId == projectId && stations.Contains(f.Station) && f.TransDateTime >= begin && f.TransDateTime <= end)
                        select m;
            return query.AsNoTracking();
        }
        /// <summary>
        ///  andon 异常明细
        /// </summary>
        /// <param name="project_id"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="andontstate"></param>
        /// <returns></returns>
        public IEnumerable<ResponseAndonDetials> AndonDetials(int project_id, long start, long end, int andontstate)
        {

            var query = from f in _tpmDbContext.siger_andon_info
                        join ex in _tpmDbContext.siger_andon_expection_type on f.expection_type equals ex.id into extemp
                        from ex in extemp.DefaultIfEmpty()
                        join usg in _tpmDbContext.siger_project_usergroup on ex.usergroup equals usg.id into usgtemp
                        from usg in usgtemp.DefaultIfEmpty()
                        join s in _tpmDbContext.siger_project_section on usg.sectionid equals s.id into stemp
                        from se in stemp.DefaultIfEmpty()
                            //join s in _context.siger_project_level_section on f.station equals s.id
                            //join ls in _context.siger_project_level_section on s.parentid equals ls.id
                            // join u in _context.siger_project_user on f.handler equals u.mid
                        where f.projectid == project_id && f.create_time >= start && f.create_time <= end && f.status > andontstate && f.status < (int)AndonState.CancleAbnormal
                        select new ResponseAndonDetials
                        {
                            id = f.id,
                            section = se != null ? se.id : 0,
                            sectionTitle = se != null ? se.title : "",
                            station = usg != null ? usg.id : 0,
                            stationTitle = usg != null ? usg.title : "",
                            create_time = f.create_time,
                            handle_time = f.handle_time,
                            approve_time = f.approve_time,
                            complete_time = f.complete_time,
                            expectype = f.expection_type,
                            status = f.status,
                            creater = f.creator,
                            hanlder = f.handler,

                            // username=$"{u.name}"
                        };
            var data = query.GroupBy(g => g.id).Select(f => f.FirstOrDefault()).ToList();
            foreach (var d in data)
            {
                var details = _tpmDbContext.siger_andon_info_detail.Where(f => f.projectid == project_id && f.status != 0 && f.level == 0 && f.andon_id == d.id).ToList();
                d.approver = details.FirstOrDefault(f => f.status == (int)AndonState.Approve || f.status == (int)AndonState.Com_Approve || f.status == (int)AndonState.Recovery)?.user ?? "";

                d.complater = details.FirstOrDefault(f => f.status == (int)AndonState.Complete)?.user ?? "";

            }
            return data;

        }

        public IEnumerable<UserInfo> GetUserInfoList(int projectId)
        {
            var query = from q in _configDbContext.siger_project_user
                        join c in _configDbContext.siger_project_section on q.sectionid equals c.id into group1
                        from c in group1.DefaultIfEmpty()
                        join u1 in _configDbContext.siger_project_usergroup on q.usergroupid equals u1.id.ToString() into user1
                        from u1 in user1.DefaultIfEmpty()
                        where q.status == (int)RowState.Valid && q.projectid == projectId
                        select new UserInfo
                        {
                            mid = q.mid,
                            create_time = q.create_time == 0 ? "" : UnixTimeHelper.ConvertIntDate(q.create_time),
                            fixed_line = q.fixed_line,
                            mobile = q.mobile,
                            name = q.name,
                            sectionid = q.sectionid,
                            sectiontitle = c != null ? c.title : "",
                            sex = q.sex.ToString(),
                            usergroupid = u1 != null ? u1.id : 0,
                            usergrouptitle = u1 != null ? u1.title : "",
                            work_code = q.work_code,
                            work_email = q.work_email,
                            rank = q.rank
                        };

            return query.AsNoTracking();
        }
        /// <summary>
        /// kpi 任务列表
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="beginTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public IEnumerable<SigerProjectKpiTasklist>GetKpiTasklist(int projectId, DateTime beginTime, DateTime endTime)
        {
            var query = from m in _kpiDbContext.siger_project_kpi_tasklist.Where(f => f.projectId == projectId  && f.Busidate >= beginTime && f.Busidate <= endTime)
                        select m;
            return query;
        }

        public siger_project_section getSection(int key)
        {
            var query = from q in _configDbContext.siger_project_section.Where(f => f.id == key)
                        select q;

            return query.FirstOrDefault();
        }
        /// <summary>
        /// KPI处理结果
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="taskIds"></param>
        /// <returns></returns>
        public IEnumerable<ResponseKpiActionInfo> GetActionResult(int projectId, List<int> taskIds)
        {
            var query = from a in _kpiDbContext.siger_project_kpi_action
                        join r in _kpiDbContext.siger_project_kpi_action_result on a.TaskId equals r.TaskId
                        where a.projectId == projectId && taskIds.Contains(a.TaskId)
                        select new ResponseKpiActionInfo
                        {
                            Id = a.id,
                            TaskId = a.TaskId,
                            Plantime = a.Plantime,
                            Resultime = r.Time,
                            Expire = r.Time > a.Plantime ? 1 : 0

                        };

            return query.GroupBy(g => g.Id).Select(s => s.FirstOrDefault());

        }

        /// <summary>
        /// TPM 记录明细
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="pid"></param>
        /// <returns></returns>
        public List<ResponseRepairWorkCount> GetRepairWorkCount(long start, long end, int pid)
        {
            var ret = new List<ResponseRepairWorkCount>();
            // 1待接单，2已接单;待签到，3待维修，4签到;待复线，5维修完成,待反馈，6已完成，7已完成，0->删除
            var query = from r in _tpmDbContext.siger_project_repair
                        join t in _tpmDbContext.siger_andon_expection_type on r.expection_id equals t.id
                        join usg in _tpmDbContext.siger_project_usergroup on t.usergroup equals usg.id into utemp
                        from usg in utemp.DefaultIfEmpty()
                        where r.projectid == pid && r.status > 1 && r.createtime >= start && r.createtime <= end
                        select new TempRepairList
                        {
                            id = r.id,
                            creatmid = r.mid,
                            takemid = r.takemid,
                            signmid = r.signmid,
                            complatemid = r.completemid,
                            excptype = r.expection_id,
                            typeStation = usg != null ? usg.title : "",
                            status = r.status
                        };

            var excpType = query.GroupBy(g => g.excptype).ToList();
            foreach (var type in excpType)
            {
                var typeObj = type.FirstOrDefault();
                var typelist = type.ToList();
                var mode1 = new ResponseRepairWorkCount
                {
                    title = typeObj.typeStation,
                    handle = typelist.Count(),
                    handle_count = typelist.GroupBy(g => g.takemid).Count(),
                    sign = typelist.Count(),
                    sign_count = typelist.GroupBy(g => g.signmid).Count(),
                    complete = typelist.Count(),
                    complete_count = typelist.GroupBy(g => g.complatemid).Count(),
                };
                ret.Add(mode1);
            }
            return ret;
        }

    }
}
