using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Dapper.ResultData;
using Siger.Middlelayer.Share.Models;

namespace Siger.Middlelayer.Dapper.Utilities
{
    public class YieldMangaer
    {
        public static IList<ProgramYield> GetProgramNosSync(IEnumerable<CncProduction> yields, string start,
            int machineId, int maxEndTime)
        {
            var grouped = new List<CncProduction>();

            var machineYields = yields.ToList();
            var groupBy = 0;
            //var idid = machineYields.Select(f=>f.programCode).Distinct().ToList();
            //for (int i = 0; i < idid.Count(); i++)
            //{
            //    for (var j = 0; j < machineYields.Count - 1; j++)
            //    {
            //        var temp = machineYields[j];
            //        if (machineYields[j].programCode==idid[i])
            //        {
            //            var tempNext = machineYields[j];
            //            temp.GroupedId = groupBy;
            //            grouped.Add(temp);
            //        }  
            //    }
            //    groupBy++;
            //}
            #region 原逻辑--暂时不删
            for (var i = 0; i < machineYields.Count - 1; i++)
            {
                var temp = machineYields[i];
                var tempNext = machineYields[i + 1];
                temp.GroupedId = groupBy;
                if (temp.programCode != tempNext.programCode)
                {
                    groupBy++;
                }

                grouped.Add(temp);
            }

            var lastSateList = machineYields.Last();
            if (grouped.Any())
            {
                var tempLast = grouped.Last();
                if (lastSateList.programCode != tempLast.programCode)
                {
                    lastSateList.GroupedId = groupBy + 1;
                }
                else
                {
                    lastSateList.GroupedId = groupBy;
                }
            }

            grouped.Add(lastSateList);
            #endregion           

            //合并程序号
            var programNos = new List<ProgramYield>();
            var groups = from p in grouped
                         group p by new
                         {
                             p.GroupedId,
                             p.machineID,
                             p.comment,
                             p.programCode
                         }
                into g
                         select g;

            var machineGroups = groups.Where(q => q.Key.machineID == machineId);
            var index = 1;
            var startTime = string.Empty;
            var endTime = string.Empty;
            foreach (var groupedSate in machineGroups)
            {
                if (index == 1)
                {
                    startTime = start;
                }

                endTime = groupedSate.Max(q => q.dataTime).ToString(ParameterConstant.DateTimeFormat);
                if (index == machineGroups.Count())
                {
                    endTime = UnixTimeHelper.ConvertIntDateTime(maxEndTime);
                }


                var program = new ProgramYield
                {
                    startTime = startTime,
                    endTime = endTime,
                    machineId = machineId,
                    programNo = groupedSate.Key.programCode,
                    yield = groupedSate.ToList().Sum(m => m.yield),
                    totaltime = groupedSate.ToList().Sum(m => m.CycleTime),
                    comment = groupedSate.Key.comment
                };
                if (program.yield != 0 && program.totaltime != 0)
                {
                    program.averagetime = Math.Round(program.totaltime / program.yield, 2);
                }
                else
                {
                    program.averagetime = 0;
                }
                startTime = program.endTime;

                programNos.Add(program);
                index++;
            }

            return programNos;
        }

        public static IList<ProgramYield> GetProgramNosSyncTwo(IEnumerable<CncProduction> yields, string start,
           int machineId, int maxEndTime)
        {
            var grouped = new List<CncProduction>();

            var machineYields = yields.ToList();
            var groupBy = 0;
            var idid = machineYields.Select(f => f.programCode).Distinct().ToList();
            for (int i = 0; i < idid.Count(); i++)
            {
                for (var j = 0; j < machineYields.Count; j++)
                {
                    var temp = machineYields[j]; 
                    if (machineYields[j].programCode == idid[i])
                    {
                        var tempNext = machineYields[j];
                        temp.GroupedId = groupBy;
                        grouped.Add(temp);
                    }
                }
                groupBy++;
            }
            #region 原逻辑--暂时不删
            //for (var i = 0; i < machineYields.Count - 1; i++)
            //{
            //    var temp = machineYields[i];
            //    var tempNext = machineYields[i + 1];
            //    temp.GroupedId = groupBy;
            //    if (temp.programCode != tempNext.programCode)
            //    {
            //        groupBy++;
            //    }

            //    grouped.Add(temp);
            //}

            //var lastSateList = machineYields.Last();
            //if (grouped.Any())
            //{
            //    var tempLast = grouped.Last();
            //    if (lastSateList.programCode != tempLast.programCode)
            //    {
            //        lastSateList.GroupedId = groupBy + 1;
            //    }
            //    else
            //    {
            //        lastSateList.GroupedId = groupBy;
            //    }
            //}

            //grouped.Add(lastSateList);
            #endregion           

            //合并程序号
            var programNos = new List<ProgramYield>();
            var groups = from p in grouped
                         group p by new
                         {
                             p.GroupedId,
                             p.machineID,
                             p.programCode
                         }
                into g
                         select g;

            var machineGroups = groups.Where(q => q.Key.machineID == machineId);
            var index = 1;
            var startTime = string.Empty;
            var endTime = string.Empty;
            foreach (var groupedSate in machineGroups)
            {
                if (index == 1)
                {
                    startTime = start;
                }

                endTime = groupedSate.Max(q => q.dataTime).ToString(ParameterConstant.DateTimeFormat);
                if (index == machineGroups.Count())
                {
                    endTime = UnixTimeHelper.ConvertIntDateTime(maxEndTime);
                }


                var program = new ProgramYield
                {
                    startTime = startTime,
                    endTime = endTime,
                    machineId = machineId,
                    programNo = groupedSate.Key.programCode,
                    yield = groupedSate.ToList().Sum(m => m.yield),
                    totaltime = groupedSate.ToList().Sum(m => m.CycleTime),
                };
                if (program.yield != 0 && program.totaltime != 0)
                {
                    program.averagetime = Math.Round(program.totaltime / program.yield, 2);
                }
                else
                {
                    program.averagetime = 0;
                }
                startTime = program.endTime;

                programNos.Add(program);
                index++;
            }

            return programNos;
        }

        public static async Task<IList<ProgramYield>> GetProgramNos(IEnumerable<CncProduction> yields, string start,
            int machineId, int maxEndTime)
        {
            return await Task.Run(() => GetProgramNosSync(yields, start, machineId, maxEndTime));
        }

        public static async Task<IList<ProgramYield>> GetProgramNosTwo(IEnumerable<CncProduction> yields, string start,
            int machineId, int maxEndTime)
        {
            return await Task.Run(() => GetProgramNosSyncTwo(yields, start, machineId, maxEndTime));
        }

        public static IList<MachineProgramNo> GetMachineProgramNos(IEnumerable<CncProduction> yields, string start,
            IEnumerable<int> machineIds, int maxEndTime)
        {
            var programNos = new List<ProgramYield>();
            foreach (var machineId in machineIds)
            {
                var machineYileds = yields.Where(q => q.machineID == machineId).ToList();
                if (machineYileds.Any())
                {
                    var pros = GetProgramNos(machineYileds, start, machineId, maxEndTime).Result;
                    programNos.AddRange(pros);
                }
            }

            var machineProgramNos = new List<MachineProgramNo>();
            foreach (var programNo in programNos)
            {
                var program = machineProgramNos.FirstOrDefault(q =>
                    q.machineId == programNo.machineId && q.programNo == programNo.programNo);
                if (program == null)
                {
                    machineProgramNos.Add(new MachineProgramNo
                    {
                        machineId = programNo.machineId,
                        programNo = programNo.programNo,
                        TimeRanges = new List<TimeRange>
                            {new TimeRange(programNo.startTime.ToDateTime(), programNo.endTime.ToDateTime())}
                    });
                }
                else
                {
                    program.TimeRanges.Add(new TimeRange(programNo.startTime.ToDateTime(),
                        programNo.endTime.ToDateTime()));
                }
            }

            return machineProgramNos;
        }

        public static IList<MachineYield> GetProductRoutesOEE(IList<ProgramYield> programs,
            IEnumerable<BeatSetInfo> beats,
            IEnumerable<MachineRestInfo> times, int companyId, int projectId)
        {
            var result = new List<MachineYield>();
            if (beats == null)
            {
                beats = new List<BeatSetInfo>();
            }
            var allMachinIds = programs.Select(m => m.machineId).Distinct();
            foreach (var machinId in allMachinIds)
            {
                var allProgramNos = programs.Where(q => q.machineId == machinId).Select(m => m.programNo).Distinct();

                foreach (var programNo in allProgramNos)
                {
                    var entity = new MachineYield
                    {
                        machine_id = machinId,
                        program_code = programNo,
                        product_name = "",
                        route_name = ""
                    };
                    double totalActualYield = 0;
                    double averagetime = 0;
                    double totaltime = 0;
                    var programInfoes = programs.Where(q => q.programNo == programNo && q.machineId == machinId);
                    foreach (var info in programInfoes)
                    {
                        var start = info.startTime.ToDateTime();
                        var end = info.endTime.ToDateTime();

                        var beat = beats.FirstOrDefault(q => q.machineID == machinId && q.process_number == programNo
                                                                                     && q.start_time <= end && q.end_time >= end);
                        if (!string.IsNullOrWhiteSpace(info.comment))
                        {
                            var str = info.comment.Split('/');
                            if (str.Length == 2)
                            {
                                var beatSet = beats.FirstOrDefault(q => q.route_number == str[1].ToStr() && q.drawing_number == str[0].ToStr() && q.start_time <= end && q.end_time >= end && q.status == (int)RowState.Valid && q.projectID == projectId);
                                entity.product_name = beatSet != null ? beatSet.product_name_text : "";
                                entity.route_name = beatSet != null ? beatSet.route_name : "";
                            }
                        }
                        var actualYield = info.yield * (beat?.yieldrate ?? 1);
                        totalActualYield += actualYield;
                        averagetime = info.averagetime;
                        totaltime = info.totaltime;
                    }
                    entity.yield = (int)totalActualYield;
                    entity.averagetime = averagetime;
                    entity.totaltime = totaltime;
                    result.Add(entity);
                }
            }
            return result;
        }
    }
}
