using Siger.ApiDashboard.Tasks.Model;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.Dapper.Data;
using Siger.Middlelayer.Dapper.SearchCondition;
using Siger.Middlelayer.Dapper.Utilities.Oee;
using Siger.Middlelayer.Dapper.Utilities.Slice;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Utility.Helpers;
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading.Tasks;
namespace Siger.ApiDashboard.Tasks.Reports
{
    public class MouduleFjwReport
    {

        public IEnumerable<FjwReportResult> GetReportResult(siger_project_monthreport_config config, siger_project_monthreport_config_template template)
        {
            var result = new List<FjwReportResult>();
            try
            {

                var fjwReport = new FjwReportResult
                {
                    type = "CustomizationReport",
                    title = "富士和机械"
                };

                var lineTille = GetLineTitle(config);
                fjwReport.line = lineTille;
                fjwReport.productCode = ReportDbHelper.Instance.GetProductCode(config);
                var range = ReportDbHelper.Instance.TimeRange(config);
                var timeRange = range.StartTime + " - " + range.EndTime;
                fjwReport.datetime = timeRange;
                var machines = GetMachineByConfig(config);
                if (!machines.Any())
                    return result;

                var sectionIds = GetSectionIdsByConfig(config);
                //追溯
                var traceData = ReportDbHelper.Instance.GetTraceInfo(sectionIds, config.project_id, range.StartTime, range.EndTime);

                var traceDataStation = traceData.GroupBy(g => g.Station).OrderBy(o => o.Key);
                var eChart = new EchartData();
                var eChart2 = new EchartDataColor();
                var colorlst = new List<string> { "#D87DCE", "#84CDE6", "#32C7C7", "#7EDBBA", "#4AC76F" };
                //良率统计
                foreach (var station in traceDataStation)
                {
                    var stationlst = station.ToList();
                    double inpttl = stationlst.Select(s => s.Sn).Distinct().Count();

                    var okttl = stationlst.Where(s => s.Result.ToUpper() == "OK").GroupBy(g => g.Sn).Count();
                    var ngttl = inpttl - okttl;
                    var percent = (okttl / inpttl) * 100;
                    var percentRounding = Math.Round(percent, 2);
                    fjwReport.tableData1.Add(new TableColumn
                    {
                        one = station.Key,
                        two = inpttl.ToStr(),
                        three = okttl.ToStr(),
                        four = ngttl.ToStr(),
                        five = $"{percentRounding}%"
                    });
                    eChart.xAxis.Add(station.Key);
                    eChart.series.Add(percentRounding.ToStr());

                    if (percentRounding < 100)
                    {
                        fjwReport.tableData2.Add(new TableColumn
                        {
                            one = station.Key,
                            two = ngttl.ToStr(),
                        });
                        var randon = new Random().Next(1, 4);
                        eChart2.color.Add(colorlst[randon]);
                        eChart2.xAxis.Add(station.Key);
                        eChart2.series.Add(percentRounding.ToStr());


                    }
                }
                fjwReport.echartData1.Add(eChart);
                //不良率统计
                fjwReport.echartData2.Add(eChart2);

                //切片分析
                var sliceData = SliceManager.GetMachineSlice(range.StartTime, range.EndTime, machines, config.company_id, config.project_id, "CVT2", 2).Result;

                var totalDay = range.EndTime.Subtract(range.StartTime).TotalDays;
                var totalMachine = machines.Count;
                var totalDown = sliceData.data.hour1;
                var totalDownPercent = sliceData.data.num1;
                var totalRun = sliceData.data.hour2;
                var totalRunPercent = sliceData.data.num2;
                var totalDebug = sliceData.data.hour3;
                var totalDebugPercent = sliceData.data.num3;
                var totalFree = sliceData.data.hour4;
                var totalFreePercent = sliceData.data.num4;
                var totalFault = sliceData.data.hour5;
                var totalFaultPercent = sliceData.data.num5;

                var avgDown = 0d;
                var avgRun = 0d;
                var avgDebug = 0d;
                var avgFree = 0d;
                var avgFault = 0d;
                if (totalDay > 0)
                {
                    avgDown = Math.Round(totalDown / totalDay / totalMachine, 2);
                    avgRun = Math.Round(totalRun / totalDay / totalMachine, 2);
                    avgDebug = Math.Round(totalDebug / totalDay / totalMachine, 2);
                    avgFree = Math.Round(totalFree / totalDay / totalMachine, 2);
                    avgFault = Math.Round(totalFault / totalDay / totalMachine, 2);

                }
                fjwReport.tableData3 = $"<div>关机时长 <span>{totalDown}小时</span>，平均每天每台关机<span>{avgDown}小时</span></div><div>运行时长 <span>{totalRun}小时</span>，平均每天每台运行<span>{avgRun}小时</span></div><div>调试时长 <span>{totalDebug}小时</span>，平均每天每台调试<span>{avgDebug}小时</span></div><div>空闲时长 <span>{totalFree}小时</span>，平均每天每台空闲<span>{avgFree}小时</span></div><div>报警时长 <span>{totalFault}小时</span>，平均每天每台报警<span>{avgFault}小时</span></div>";


                fjwReport.echartData3.Add(
                    new EchartData3
                    {
                        color = new List<string> { "#D87DCE", "#84CDE6", "#32C7C7", "#7EDBBA", "#4AC76F" },
                        xAxis = new List<string> { "关机", "运行", "调试", "空闲", "报警" },
                        series = new List<EchartPin> { new EchartPin { value=totalDownPercent.ToStr(), name= "关机" },
                    new EchartPin { value=totalRunPercent.ToStr(), name= "运行" },
                    new EchartPin { value=totalDebugPercent.ToStr(), name= "调试" },
                    new EchartPin { value=totalFreePercent.ToStr(), name= "空闲" },
                    new EchartPin { value=totalFaultPercent.ToStr(), name= "报警" }
                     }
                    });



                var sliceRepositoey = new SliceSateRepository(config.company_id, config.project_id);
                var sliceSates = sliceRepositoey.GetCncSliceSates(machines, range.StartTime.ToString(ParameterConstant.DateTimeFormat), range.EndTime.ToString(ParameterConstant.DateTimeFormat));
                var times = ReportDbHelper.Instance.GetRestTimesByMachine(machines, config.project_id);
                var oee = OeeManager.GetOeeByTime(range.StartTime, range.EndTime, sliceSates, machines, null, times);
                var MonthOee = Math.Round(oee.OEE1, 2);

                var preMonthStart = MonthHelper.FirstDayOfPreviousMonth(range.StartTime);
                var preMonthEnd = MonthHelper.LastDayOfPrdviousMonth(range.EndTime);
                var sliceSates2 = sliceRepositoey.GetCncSliceSates(machines, preMonthStart.ToString(ParameterConstant.DateTimeFormat), preMonthEnd.ToString(ParameterConstant.DateTimeFormat));
                var preOee = OeeManager.GetOeeByTime(preMonthStart, preMonthEnd, sliceSates2, machines, null, times);
                var PreMonthOee = Math.Round(preOee.OEE1, 2);

                var addPercent = Math.Round(PreMonthOee / MonthOee, 2);

                var monthOees = GetMonthOee(sliceRepositoey, config, range.StartTime, range.EndTime, machines);
                var bestOeeDate = string.Empty;
                var bestOee = 0d;
                var badOeeDate = string.Empty;
                var badOee = 0d;
                if (monthOees.Any())
                {
                    var orderbyOee = monthOees.OrderByDescending(o => o.Val).ToList();
                    bestOeeDate = orderbyOee[0].Date;
                    bestOee = orderbyOee[0].Val;
                    badOeeDate = orderbyOee[orderbyOee.Count() - 1].Date;
                    badOee = orderbyOee[orderbyOee.Count() - 1].Val;


                    var oeeData = new EchartData();
                    //top 5;
                    var step = 0;
                    foreach (var d in orderbyOee)
                    {
                        step += 1;
                        if (step == 5)
                            break;
                        oeeData.xAxis.Add(d.Date);
                        oeeData.yAxis.Add(d.Val.ToStr());
                    }
                    fjwReport.echartData4.Add(oeeData);


                }
                fjwReport.tableData4 = $"<div>本月设备综合OEE<span>{MonthOee}%</span>，同比上月增幅<span>{addPercent}%</span></div><div>OEE最佳日期{bestOeeDate}<span>{bestOee}%</span></div><div>OEE最差日期{badOeeDate} <span>{badOee}%</span></div>";


                //上个月切片
                var preSliceData = SliceManager.GetMachineSlice(preMonthStart, preMonthEnd, machines, config.company_id, config.project_id, "CVT2", 2).Result;

                var preTotalDown = preSliceData.data.hour1;
                var preTotalDownPercent = preSliceData.data.num1;
                var chaDown = totalDownPercent - preTotalDownPercent;

                var preTotalRun = preSliceData.data.hour2;
                var preTotalRunPercent = preSliceData.data.num2;
                var chaRun = totalRunPercent - preTotalRunPercent;

                var preTotalDebug = preSliceData.data.hour3;
                var preTotalDebugPercent = preSliceData.data.num3;
                var chaDebug = totalDebugPercent - preTotalDebugPercent;

                var preTotalFree = preSliceData.data.hour4;
                var preTotalFreePercent = preSliceData.data.num4;
                var chaFree = totalFreePercent - preTotalFreePercent;

                var preTotalFault = preSliceData.data.hour5;
                var preTotalFaultPercent = preSliceData.data.num5;
                var chaFault = totalFaultPercent - preTotalFaultPercent;

                fjwReport.tableData5.Add(new TableColumn
                {
                    one = "关机",
                    two = sliceData.data.hour1.ToStr(),
                    three = $"{sliceData.data.num1.ToStr()}%",
                    four = $"{ Math.Round(chaDown, 2).ToStr()}%"
                });
                fjwReport.tableData5.Add(new TableColumn
                {
                    one = "运行",
                    two = sliceData.data.hour2.ToStr(),
                    three = $"{ sliceData.data.num2.ToStr()}%",
                    four = $"{ Math.Round(chaRun, 2).ToStr() }%"
                });
                fjwReport.tableData5.Add(new TableColumn
                {
                    one = "调试",
                    two = sliceData.data.hour3.ToStr(),
                    three = $"{ sliceData.data.num3.ToStr()}%",
                    four = $"{ Math.Round(chaDebug, 2).ToStr()}%"
                });
                fjwReport.tableData5.Add(new TableColumn
                {
                    one = "空闲",
                    two = sliceData.data.hour4.ToStr(),
                    three = $"{ sliceData.data.num4.ToStr()}%",
                    four = $"{ Math.Round(chaFree, 2).ToStr()}%"
                });
                fjwReport.tableData5.Add(new TableColumn
                {
                    one = "故障",
                    two = sliceData.data.hour5.ToStr(),
                    three = $"{ sliceData.data.num5.ToStr()}%",
                    four = $"{ Math.Round(chaFault, 2).ToStr()}%"
                });
                fjwReport.tableText5 = $"{lineTille}线本月设备运行总时长<span>{totalRun}</span>小时，同比上月增加<span>{totalRun - preTotalRun}</span>小时，增幅达<span>{Math.Round(chaRun, 2)}%</span>";

                fjwReport.echartData5.Add(new EchartData
                {
                    xAxis = new List<string> { "关机", "运行", "调试", "空闲", "报警" },
                    yAxis = new List<string> { sliceData.data.num1.ToStr(), sliceData.data.num2.ToStr(), sliceData.data.num3.ToStr(), sliceData.data.num4.ToStr(), sliceData.data.num5.ToStr() },
                    series = new List<string> { preSliceData.data.num1.ToStr(), preSliceData.data.num2.ToStr(), preSliceData.data.num3.ToStr(), preSliceData.data.num4.ToStr(), preSliceData.data.num5.ToStr() }
                });


                ////1 设备报警

                var cncExceptionRepository = new AlarmAnalysResultRepository(config.company_id, config.project_id);
                var condition = new CncAlarmAnalysResultCondition
                {
                    STime = range.StartTime.ToString(ParameterConstant.DateTimeFormat),
                    ETime = range.EndTime.ToString(ParameterConstant.DateTimeFormat),
                };
                var exceptions = cncExceptionRepository.GetNoPagedCncExceptionParamsSates(condition);
                var excepttl = exceptions.Count();

                var execpTimettl = exceptions.Sum(s => (s.Etime - s.Stime).TotalSeconds) / 60; //分
                execpTimettl = Math.Round(execpTimettl);
                var avgExecp = 0d;
                if (execpTimettl > 0)
                {
                    avgExecp = Math.Round(excepttl / execpTimettl, 2);
                }
                var grpExecp = exceptions.GroupBy(g => g.code);
                var cncAlarms = new List<CndAlarm>();
                foreach (var grp in grpExecp)
                {
                    // var curCodeCnt=grp.Sum(s => (s.Etime - s.Stime).TotalSeconds) / 60; //分
                    cncAlarms.Add(new CndAlarm
                    {
                        Code = grp.Key,
                        //   Total= curCodeCnt,
                        Count = grp.Count()
                    });
                }
                var topFive = cncAlarms.OrderByDescending(d => d.Count).Take(5);
                var topFiveCount = topFive.Sum(s => s.Count);
                var topFiveCountPercent = 0d;
                if (excepttl > 0)
                {
                    topFiveCountPercent = Math.Round(topFiveCount / excepttl, 2) * 100;
                }
                var topFiveEchart = new EchartData();
                foreach (var top in topFive)
                {
                    topFiveEchart.xAxis.Add(top.Code);
                    topFiveEchart.series.Add(top.Count.ToStr());
                }

                fjwReport.echartData6.Add(topFiveEchart);

                fjwReport.tableData6 = $"<div>本月设备共报警<span>{excepttl}</span>次，平均每次报警时长{avgExecp}分钟。</div><div>报警次数最多的前5个报警代码共报警{topFiveCount}次，占总报警次数的<span>{topFiveCountPercent}%</span></div>";


                var dtstart = UnixTimeHelper.ConvertDataTimeLong(range.StartTime);
                var dtend = UnixTimeHelper.ConvertDataTimeLong(range.EndTime);
                //刀具报警
                var dapperData = new ToolAlarmRepository(config.company_id, config.project_id);
                var Kmdata = dapperData.GetToolAlarm(machines, dtstart, dtend, 0).ToList();
                var brokenCnt = Kmdata.Where(s => s.Alarm_grade == 4).Count();
                var destroyed = Kmdata.Where(s => s.Alarm_grade == 5).Count();

                fjwReport.tableData7 = $"本月共发生崩刃{brokenCnt}次，断刀{destroyed}次";

                var echartData7 = new EchartDataTool
                {
                    legend = new List<string> { "质量异常", "计数寿命到", "磨损过度", "崩刃", "断刀" }
                };
                var alramGrage = SetKmData(Kmdata);
                var grpKmdata = alramGrage.GroupBy(d => d.DateTime).OrderBy(d => d.Key);
                var zlttl = 0;
                var smttl = 0;
                var msttl = 0;
                var brttl = 0;
                var ddttl = 0;
                foreach (var km in grpKmdata)
                {
                    var kmlst = km.ToList();
                    var zlCnt = kmlst.Where(f => f.Grade == 1).Count();
                    var smCnt = kmlst.Where(f => f.Grade == 2).Count();
                    var msCnt = kmlst.Where(f => f.Grade == 3).Count();
                    var brCnt = kmlst.Where(f => f.Grade == 4).Count();
                    var ddCnt = kmlst.Where(f => f.Grade == 5).Count();

                    echartData7.xAxis.Add(km.Key);
                    zlttl += zlCnt;
                    echartData7.yAxis1.Add(zlCnt);
                    smttl += smCnt;
                    echartData7.yAxis2.Add(smCnt);
                    msttl += msCnt;
                    echartData7.yAxis3.Add(msCnt);
                    brttl += brCnt;
                    echartData7.yAxis4.Add(brCnt);
                    ddttl += ddCnt;
                    echartData7.yAxis5.Add(ddCnt);
                }
                fjwReport.echartData7.Add(echartData7);

                var echartData8 = new EchartData();
                echartData8.yAxis = new List<string> { "质量异常", "计数寿命到", "磨损过度", "崩刃", "断刀" };
                echartData8.series = new List<string> { zlttl.ToStr(), smttl.ToStr(), msttl.ToStr(), brttl.ToStr(), ddttl.ToStr() };

                fjwReport.echartData8.Add(echartData8);

                result.Add(fjwReport);
            }
            catch (Exception x)
            {
                Logger.WriteLineError(x.ToStr());
            }

            return result;
        }
        private List<KmAlarm> SetKmData(IEnumerable<ToolAlarmStatis> data)
        {
            var Result = new List<KmAlarm>();
            foreach (var d in data)
            {
                var alarmTime = UnixTimeHelper.ConvertStringDateTime(d.Alarmtime.ToStr());
                Result.Add(new KmAlarm
                {
                    MachineId = d.MachineID,
                    DateTime = alarmTime.ToShortDateString(),
                    Grade = d.Alarm_grade
                });
            }
            return Result;
        }
        private List<int> GetMachineByConfig(siger_project_monthreport_config config)
        {
            var result = new List<int>();
            var templates = ReportDbHelper.Instance.GetRptTemplates(config.id);
            foreach (var template in templates)
            {
                result.AddRange(ReportDbHelper.Instance.GetMachineIds(template).ToList());
            }
            return result;
        }
        private List<int> GetSectionIdsByConfig(siger_project_monthreport_config config)
        {
            var result = new List<int>();
            var templates = ReportDbHelper.Instance.GetRptTemplates(config.id);
            foreach (var template in templates)
            {
                var sectionIds = template.param.Split(',').Select(t => t.ToInt());
                result.AddRange(sectionIds);
            }
            return result;
        }
        private string GetLineTitle(siger_project_monthreport_config config)
        {
            var templates = ReportDbHelper.Instance.GetRptTemplates(config.id);
            if (!templates.Any())
                return "";
            var template = templates.FirstOrDefault();
            return ReportDbHelper.Instance.LineTitle(template);
        }

        public IEnumerable<MonthOeeObj> GetMonthOee(SliceSateRepository sliceRepositoey, siger_project_monthreport_config config, DateTime beginDate, DateTime endDate, List<int> machineIds)
        {
            var result = new List<MonthOeeObj>();
            var patchId = 0;
            var interal = DateTimeHelper.GetInteral(patchId);
            var dates = DateTimeHelper.GetDateTimes(beginDate, endDate, patchId);
            foreach (var date in dates)
            {
                DateTime start;
                DateTime end;
                string dateTime;
                if (patchId == 0 || patchId == 1)
                {
                    start = date;
                    end = date.AddDays(interal).AddSeconds(-1) > DateTime.Now
                        ? DateTime.Now
                        : date.AddDays(interal).AddSeconds(-1);
                    dateTime = end.ToString(ParameterConstant.DateFormat);
                }
                else
                {
                    start = date.AddDays(1 - date.Day);
                    end = date.AddDays(1 - date.Day).Date.AddMonths(1).AddSeconds(-1) > DateTime.Now
                        ? DateTime.Now
                        : date.AddDays(1 - date.Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                    dateTime = end.ToString(ParameterConstant.YearMonthFormat);
                }
                var sliceSates = sliceRepositoey.GetCncSliceSates(machineIds, start.ToString(ParameterConstant.DateTimeFormat), end.ToString(ParameterConstant.DateTimeFormat));
                //稼动率
                if (sliceSates.Any())
                {
                    var times = ReportDbHelper.Instance.GetRestTimesByMachine(machineIds, config.project_id);
                    var oee = OeeManager.GetOeeByTime(start, end, sliceSates, machineIds, null, times);
                    var val = Math.Round(oee.OEE1, 2);

                    result.Add(new MonthOeeObj
                    {
                        Date = dateTime,
                        Val = val
                    });
                }
            }
            return result;
        }
        public class MonthOeeObj
        {
            public string Date { get; set; }
            public double Val { get; set; }
        }
        public class CndAlarm
        {
            public string Code { get; set; }
            /// <summary>
            /// 时长
            /// </summary>
            public double Total { get; set; }
            /// <summary>
            /// 次数
            /// </summary>
            public double Count { get; set; }
        }
        public class KmAlarm
        {
            public int MachineId { get; set; }
            public string DateTime { get; set; }
            /// <summary>
            ///1.质量 2 寿命,3 磨损,4 崩刃,5 断刀
            /// </summary>
            public int Grade { get; set; }

        }
    }
}
