using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.AccRepository;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Data.Acc;
using Siger.Middlelayer.Repository.Repositories.Interface;

namespace Siger.ApiACC.Controllers
{
    public class AccDashboardController : BaseController
    {
        private readonly ISigerTrSnTraceRepository _trSnTrace;
        private readonly ISigerCheckItem _checkItem;
        private readonly ISigerAccTraceRepository _snTraceDetails;
        private readonly ISnListRepository _snList;
        private readonly ISigerTrMaterialsRepository _trMaterials;
        private readonly ISigerProjectLevelSectionRepository _levelSection;
        private readonly ISigerUserRepository _sigerUser;
        private readonly ISigerRoutingInStation _routingInStation;

        public AccDashboardController(ApiAccDbContext apiAccDbContext, ISigerTrSnTraceRepository trSnTraceRepository, ISigerCheckItem checkItem, ISigerAccTraceRepository snTraceDetails
            , ISnListRepository snList, ISigerTrMaterialsRepository trMaterials, ISigerProjectLevelSectionRepository levelSection, ISigerUserRepository sigerUser, ISigerRoutingInStation routingInStation)
        {
            _trSnTrace = trSnTraceRepository;
            _checkItem = checkItem;
            _snTraceDetails = snTraceDetails;
            _snList = snList;
            _trMaterials = trMaterials;
            _levelSection = levelSection;
            _sigerUser = sigerUser;
            _routingInStation = routingInStation;
        }
        /// <summary>
        /// 获取某一工站所有需要测量上下限的 产品信息
        /// </summary>
        /// <param name="SectionId"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetChkItemByLine(int SectionId)
        {

                var list = _checkItem.GetList(f =>f.Station==SectionId && f.projectId==ProjectId &&  f.CheckType.ToLower() == "v" && f.status == (int)RowState.Valid, "TransDateTime");
                if (!list.Any())
                    throw new BadRequestException(CommonEnum.RecordNotFound);

                return new PagedObjectResult(list, list.Count());

        }

        /// <summary>
        /// 获取某一产品上下限实际值
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetUpdownlimitByProduct([FromBody]RequestUpdownlimit updownlimit)
        {
            try
            {
                var lst = new List<ReponseUpdownLimit>();
                int seq = 1;
                var stations = _trSnTrace.GetSonLevelSectionIds(updownlimit.SectionId, ProjectId);
                var itemSetting = _checkItem.GetList(f =>
                        stations.Contains(f.Station) && f.Item == updownlimit.Item && f.status == (int)RowState.Valid)
                    .FirstOrDefault();
                if (itemSetting == null)
                {
                    return new ObjectResult(AccEnum.CheckItemSettingNull);
                }
                var tDetail = _snTraceDetails.GetList(f => f.Item == updownlimit.Item && f.status == (int)RowState.Valid && f.projectId == ProjectId, "TransDateTime");
                if (!tDetail.Any())
                {
                    throw new BadRequestException(AccEnum.EmtyResult);
                }
                var currentSn = tDetail.First().SN;
                var snObj = _snList
                    .GetList(f => f.SN == currentSn && f.projectId == ProjectId && f.status == (int)RowState.Valid)
                    .FirstOrDefault();
                if (snObj == null)
                {
                    throw new BadRequestException(AccEnum.Busi_SN_Null);
                }
                var pid = snObj.ProductCode;
                foreach (var d in tDetail)
                {
                    if (seq == updownlimit.Limit)
                        break;
                    lst.Add(new ReponseUpdownLimit()
                    {
                        Seq = seq,
                        Value = d.Value,
                        ProductId = pid,
                        Min = itemSetting.Min,
                        Max = itemSetting.Max,
                        Time = d.TransDateTime
                    });
                    seq += 1;
                }

                lst = lst.OrderBy(o => o.Time).ToList();
                return new PagedObjectResult(lst, lst.Count());
            }
            catch (Exception e)
            {
                Logger.WriteLineError("GetUpdownlimitByProduct failed, error: " + e.Message);
                return new ObjectResult(CommonEnum.SystemExcetion);
            }
        }
        [HttpPost]
        public IActionResult GetTrackingDetail([FromBody]RequestTrackingSn trackingSn)
        {
            try
            {
                var dataSource = GetData2(trackingSn);
                return new PagedObjectResult(dataSource, dataSource.Count, trackingSn.page, trackingSn.pagesize);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("GetTrackingDetail failed, error: " + e.Message);
                return new ObjectResult(CommonEnum.SystemExcetion);
            }


        }

        [HttpGet]
        public IActionResult GetMaterial()
        {
            try
            {
                var materials = _trMaterials.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid);
                if (!materials.Any())
                    throw new BadRequestException(CommonEnum.NoData);
                var dataSource = materials.ToList();
                return new PagedObjectResult(dataSource, dataSource.Count);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("GetPn failed, error: " + e.Message);
                return new ObjectResult(CommonEnum.SystemExcetion);
            }
        }

        private RespnsePageTrackingSn GetData2(RequestTrackingSn trackingSn)
        {
            var pageTracking = new RespnsePageTrackingSn
            {
                TrackingSn = new ResponseTrackingSn { RptHeader = new List<RptHeader> { }, RptBody = new List<RptBody> { } }
            };
            var timeArr = trackingSn.TimeSpan.Split(" - ");
            if (timeArr.Count() != 2)
                return pageTracking;
            DateTime.TryParse(timeArr[0], out DateTime startTime);
            DateTime.TryParse(timeArr[1], out DateTime endTime);

            int pageCount = 0;


            IEnumerable<SNTraceInfo> conditionSn = null;
            List<TrackingSn> rptDisply = null;

            var stations = _trSnTrace.GetSonLevelSectionIds(trackingSn.SectionId, ProjectId);

            conditionSn = _trSnTrace.GetTrSNTracePagedList(stations, trackingSn.ProductID, trackingSn.Sn, startTime, endTime
                , trackingSn.Pn, trackingSn.Result).Data;
            if (!conditionSn.Any())
                return pageTracking;

            rptDisply = MergeStationData(trackingSn.Type, conditionSn, trackingSn, out pageCount).OrderByDescending(o => o.Time).ToList();
            var RoutHead = _routingInStation.GetList(f => stations.Contains(f.Station), "id").ToList();

            pageTracking.Count = pageCount;
            pageTracking.TrackingSn.RptHeader.Add(new RptHeader { Head = "SN", Items = new List<Item>() });

            //header
            for (int h = 0; h < RoutHead.Count(); h++)
            {
                var routeH = RoutHead[h];
                var RptHeader = new RptHeader { ID = routeH.Station, Head = GetStation(routeH.Station), Items = new List<Item>() };
                for (int v = 0; v < rptDisply.Count(); v++) //sn
                {
                    var routeV = rptDisply[v];
                    var hstations = routeV.Stations.Where(f => f.ID == routeH.Station).ToList().OrderBy(o => o.Time);
                    if (hstations.Any())
                    {
                        foreach (var s in hstations)
                        {
                            var oderbyS = s.Items.OrderBy(o => o.Time);
                            foreach (var chk in oderbyS)
                            {
                                if (!RptHeader.Items.Exists(f => f.Name == chk.Item))
                                {
                                    RptHeader.Items.Add(new Item { Name = chk.Item, Time = chk.Time });
                                }
                            }
                        }
                    }
                }
                // if (RptHeader.Items.Any())
                // {
                RptHeader.Items.Add(new Item { Name = "结果", Time = DateTime.Now });
                RptHeader.Items.Add(new Item { Name = "员工", Time = DateTime.Now });
                RptHeader.Items.Add(new Item { Name = "时间", Time = DateTime.Now });
                // }
                pageTracking.TrackingSn.RptHeader.Add(RptHeader);
            }
            //body
            for (int m = 0; m < rptDisply.OrderBy(o => o.SN).Count(); m++)
            {
                var RowSn = rptDisply[m];
                var rptBody = new RptBody { Sn = RowSn.SN, Mappings = new List<RptMapping>() };

                for (int i = 0; i < pageTracking.TrackingSn.RptHeader.Count(); i++)
                {
                    var headStn = pageTracking.TrackingSn.RptHeader[i];
                    if (headStn.ID == 0)
                        continue;

                    var MappingStns = RowSn.Stations.Where(f => f.ID == headStn.ID).ToList();
                    if (!MappingStns.Any())
                    {
                        rptBody.Mappings.Add(new RptMapping { Station = headStn.Head, Items = new List<List<string>>() });
                        continue;
                    }
                    var Mapping = new RptMapping { Station = headStn.Head, Items = new List<List<string>>() };

                    if (trackingSn.Type == searchType.Normal)
                    {
                        for (var s = 0; s < MappingStns.Count; s++)
                        {
                            //body
                            var ItemValues = new List<string> { };

                            foreach (var headItem in headStn.Items)
                            {
                                var exitsObj = MappingStns[s].Items.Find(e => e.Item == headItem.Name);
                                if (headItem.Name == "结果")
                                {
                                    // if (ItemValues.Any())
                                    ItemValues.Add(MappingStns[s].Result);
                                }
                                else if (headItem.Name == "员工")
                                {
                                    //  if (ItemValues.Any())
                                    ItemValues.Add(MappingStns[s].Employ);
                                }
                                else if (headItem.Name == "时间")
                                {
                                    //  if (ItemValues.Any())
                                    ItemValues.Add(MappingStns[s].Time);
                                }
                                else
                                {
                                    ItemValues.Add(exitsObj == null ? " " : exitsObj.Value);
                                }
                            }

                            Mapping.Items.Add(ItemValues);

                            rptBody.Mappings.Add(Mapping);

                        }
                    }
                    else
                    {
                        //body
                        // 返工  升序 
                        //var MappingStnsOderby = MappingStns.OrderBy(o => o.Time).ToList();
                        var mappingStnsOderby = MappingStns;
                        //var headStnOderby = headStn.Items.OrderBy(o => o.Time).ToList();
                        var headStnOderby = headStn.Items;
                        for (var s = 0; s < mappingStnsOderby.Count; s++)
                        {
                            var temp = mappingStnsOderby[s];
                            var itemValues = new List<string> { };
                            foreach (var headItem in headStnOderby)
                            {
                                var exitsObj = temp.Items.Find(f => f.Item == headItem.Name);
                                if (headItem.Name == "结果")
                                {
                                    //  if (ItemValues.Any())
                                    itemValues.Add(temp.Result);
                                }
                                else if (headItem.Name == "员工")
                                {
                                    //  if (ItemValues.Any())
                                    itemValues.Add(temp.Employ);
                                }
                                else if (headItem.Name == "时间")
                                {
                                    //  if (ItemValues.Any())
                                    itemValues.Add(temp.Time);
                                }
                                else
                                {
                                    itemValues.Add(exitsObj == null ? " " : exitsObj.Value);
                                }
                            }

                            Mapping.Items.Add(itemValues);
                        }
                        rptBody.Mappings.Add(Mapping);

                    }

                }
                pageTracking.TrackingSn.RptBody.Add(rptBody);
            }

            return pageTracking;
        }


        private IEnumerable<SNTraceInfo> ReworkCount(IEnumerable<SNTraceInfo> record, out int count)
        {
            var reWrokLst = new List<SNTraceInfo>();

            var GroupSn = record.GroupBy(g => g.SN);
            count = 0;
            foreach (var r in GroupSn)
            {
                var snStations = r.ToList();

                var groupRecord = snStations.GroupBy(g => g.Station);
                if (snStations.Count != groupRecord.Count())
                {
                    reWrokLst.AddRange(snStations);
                    count += 1;
                }
            }
            return reWrokLst;
        }
        private List<TrackingSn> MergeStationData(searchType type, IEnumerable<SNTraceInfo> Record, RequestTrackingSn trackingSn, out int count)
        {
            List<TrackingSn> TrackingSnList = new List<TrackingSn>();

            List<IGrouping<string, SNTraceInfo>> groupResult = new List<IGrouping<string, SNTraceInfo>>();
            count = Record.GroupBy(x => x.SN).Count(x => x.Count() > 1);
            if (type == searchType.Normal)
            {
                count = Record.GroupBy(g => g.SN).Count();
                groupResult = Record.GroupBy(g => g.SN).ToList().Skip(trackingSn.Limit * (trackingSn.Offset - 1)).Take(trackingSn.Limit).ToList();
            }
            else
            {
                var reWrokLst = ReworkCount(Record, out count).ToList();
                groupResult = reWrokLst.GroupBy(g => g.SN).ToList().Skip(trackingSn.Limit * (trackingSn.Offset - 1)).Take(trackingSn.Limit).ToList();
            }

            var PageRecord = groupResult;

            foreach (var k in PageRecord)
            {
                var SnlistStation = new List<SNTraceInfo>();
                var TrackingSn = new TrackingSn
                {
                    SN = k.Key,
                    Time = k.FirstOrDefault().TransDateTime,
                    Stations = new List<TrackStation>()
                };
                var SnRecord = k.ToList().OrderBy(o => o.Station);
                var headStation = SnRecord.GroupBy(g => g.Station);

                if (type == searchType.Normal)
                {
                    foreach (var stn in headStation)
                    {
                        var doubleStn = SnRecord.Where(s => s.Station == stn.Key).OrderByDescending(d => d.LastUpdateTime).ToList();
                        var Stn = doubleStn[0];
                        // SnlistStation.Add(doubleStn[0]);
                        var itemlst = new List<ChckItem>();
                        foreach (var copai in doubleStn)
                        {
                            var seqID = copai.SeqID;
                            var query = _snTraceDetails.GetList(f =>
                                f.SeqID == seqID && f.projectId == ProjectId && f.status == (int)RowState.Valid);

                            var dts = query.ToList();
                            foreach (var d in dts)
                            {
                                var itm = string.Empty;
                                if (d.Item == d.Item3)
                                    itm = d.Item3;
                                else
                                    itm = d.Item + d.Item2 + d.Item3;

                                itemlst.Add(new ChckItem
                                {

                                    Item = itm,
                                    Result = copai.Result ?? "",
                                    Value = d.Value ?? "",
                                    Time = d.TransDateTime
                                });
                            }

                        }
                        TrackingSn.Stations.Add(new TrackStation
                        {
                            ID = Stn.Station,
                            StationName = GetStation(Stn.Station),
                            Items = itemlst,
                            Time = Stn.LastUpdateTime.ToStr(),
                            Result = Stn.Result ?? "",
                            Employ = Stn.UID == 0 ? "" : GetEmplName(Stn.UID)
                        });
                    }
                }
                else
                {
                    if (SnRecord.Count() == headStation.Count())
                        continue;
                    SnlistStation = SnRecord.ToList();


                    foreach (var stn in SnlistStation)
                    {
                        var seqID = stn.SeqID;
                        var itemlst = new List<ChckItem>();
                        var query = _snTraceDetails.GetList(f =>
                            f.SeqID == seqID && f.projectId == ProjectId && f.status == (int)RowState.Valid);
                        if (!query.Any())
                        {
                            throw new BadRequestException(AccEnum.Data_Null);
                        }
                        var dts = query.ToList();
                        foreach (var d in dts)
                        {
                            var itm = string.Empty;
                            if (d.Item == d.Item3)
                                itm = d.Item3;
                            else
                                itm = d.Item + d.Item2 + d.Item3;

                            itemlst.Add(new ChckItem
                            {

                                Item = itm,
                                Result = string.IsNullOrEmpty(stn.Result) ? "" : stn.Result,
                                Value = string.IsNullOrEmpty(d.Value) ? "" : d.Value,
                                Time = d.TransDateTime
                            });
                        }
                        TrackingSn.Stations.Add(new TrackStation
                        {
                            ID = stn.Station,
                            StationName = GetStation(stn.Station),
                            Items = itemlst,
                            Time = stn.LastUpdateTime.ToStr(),
                            Result = string.IsNullOrEmpty(stn.Result) ? "" : stn.Result,
                            Employ = stn.UID == 0 ? "" : GetEmplName(stn.UID)
                        });
                    }
                }
                TrackingSnList.Add(TrackingSn);

            }
            return TrackingSnList.OrderByDescending(d => d.Time).ToList();
        }

        private string GetEmplName(int userid)
        {
            var name = string.Empty;

            try
            {
                var user = _sigerUser.GetList(f => f.id == userid && f.status == (int)RowState.Valid).FirstOrDefault();
                if (user == null)
                    return "";
                name = user.nickname ?? "";
            }
            catch (Exception e)
            {
                Logger.WriteLineError("GetEmplName failed, error: " + e.Message);
            }
            return name;
        }

        private string GetStation(int stationId)
        {
            var station = _levelSection.Get(f => f.id == stationId && f.status == (int)RowState.Valid);
            if (station == null)
            {
                throw new BadRequestException(AccEnum.Station_Null);
            }
            return station.title;
        }

    }
}