using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository;
using System;
using System.Collections;
using Siger.Middlelayer.QmsRepository.Response;
using Siger.Middlelayer.Common.Configuration;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Log;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common.AppSettings;
using System.IO;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.QmsRepository.Request;
using System.Linq;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Redis;
using Siger.ApiQMS.Utility;
using Siger.ApiQMS.Result;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Filters;
using System.Collections.Generic;

namespace Siger.ApiQMS.Controllers
{
    public class BIController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly IInspectStandardRepository _inspectStandardRepository;
        public BIController(IUnitOfWork unitOfWork, ISigerProjectMachineAttributionRepository machineAttributionRepository,
            IInspectStandardRepository inspectStandardRepository)
        {
            _unitOfWork = unitOfWork;
            _machineAttributionRepository = machineAttributionRepository;
            _inspectStandardRepository = inspectStandardRepository;
        }

        [HttpPost]
        public async Task<IActionResult> UnivariateAnalysis([FromBody]RequestBIChart req)
        {
            return await Task.Run(() =>
            {
                if (!DateTime.TryParse(req.starttime, out DateTime stime) || !DateTime.TryParse(req.endtime, out DateTime etime))
                {
                    throw new BadRequestException(RequestEnum.TimeSpanNotNull);
                }

                var machine = _machineAttributionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.attribution == (int)MachineAttributionEnum.equipment && t.station == req.sectionid);
                if (machine == null)
                {
                    throw new BadRequestException(RequestEnum.SectionMachineNull);
                }

                var items = _inspectStandardRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    req.item.Contains(t.id)).ToList();
                if (!items.Any())
                {
                    throw new BadRequestException(RequestEnum.CheckItemNotFound);
                }

                if (req.type == QmsBIInterfaceType.Correlation && items.Count < 2)
                {
                    throw new ServerException(1950565);
                }

                var request = new RequestSpcControlChart();
                var interfaceName = EnumHelper.GetEnumDesc(req.type);
                switch (req.type)
                {
                    default:
                        request = new RequestSpcControlChart
                        {
                            setSection = req.sectionid,
                            setMachineID = machine.machine,
                            setProductID = req.productid,
                            setStarttime = (int)UnixTimeHelper.ConvertDataTimeLong(req.starttime.ToDateTime()),
                            setEndtime = (int)UnixTimeHelper.ConvertDataTimeLong(req.endtime.ToDateTime()),
                            setTargetfeature = string.Join(';', items.Select(t => t.item_en).ToList()),
                            setChunkSize = req.setChunkSize.ToInt(),
                            setGroupSize = req.setGroupSize.ToInt(),
                            setGroupNum = req.setGroupNum.ToInt()
                        };
                        break;
                }
                try
                {
                    var fileSetting = Config<FileSettings>.Get();
                    var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "PythonQMSBI");
                    
                    var pythonPath = ConfigManager.GetValue("PythonPathSetting", "PyPath", string.Empty);
                    if (string.IsNullOrEmpty(pythonPath))
                    {
                        throw new Exception("DbSetting about [PythonPathSetting] not found.");
                    }
                    var pythonScriptPath = $"{rootDir}/QmsBI.py";
                    var BIHelper = new PythonBIHelper();
                    var res = BIHelper.Run(pythonPath, pythonScriptPath, interfaceName, request);
                    //var res = GetControlChart(interfaceName, request);//请求数分服务
                    if (string.IsNullOrEmpty(res))
                    {
                        res = ReadFile("<html><body>Empty record</body></html>", Guid.NewGuid().ToString());
                    }
                    return new QmsBIResult { data = res, type = (int)req.type };
                }
                catch (Exception ex)
                {
                    Logger.WriteLineError("GetQmsBIChartError:" + ex);
                    throw new Exception(ex.Message);
                }
            });
        }

        private string GetControlChart(string interfaceName, RequestSpcControlChart request)
        {
            var host = string.Empty;
            try
            {
                var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
                foreach (var item in dbConfigs)
                {
                    if (item.Pid == ProjectId)
                    {
                        host = item.RService;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLineError(ex.ToString());
            }

            if (string.IsNullOrEmpty(host))
            {
                throw new BadRequestException(CommonEnum.GetCommCfgFailed);
            }
            var result = string.Empty;
            var time = UnixTimeHelper.GetNow();
            var fileName = $"{interfaceName}_" + time;
            var data = JsonHelper.SerializerToJsonString(request);
            var info = HttpClientHelper.HttpPost($"{host}/{interfaceName}", data);
            try
            {
                var res = JsonConvert.DeserializeObject<BIChartResult>(info);
                result = res.data;
            }
            catch
            {
                result = info;
            }
            var fileUrl = ReadFile(result, fileName);
            return fileUrl;
        }

        private string ReadFile(string fileContent, string fileName)
        {
            var htmlFolder = "ChartHtml";
            
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, htmlFolder);
            
            var filename = Path.Combine(rootDir, $"{fileName}.html");

            try
            {
                FileHelper.WriteFile(fileContent, filename);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return FileSystemHelper.CommonFileSetting.RequestPath + $"/{htmlFolder}/{fileName}.html";
        }
        /// <summary>
        /// 标准检验项关联性分析-数据展示
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetRelationAnalysis([FromBody]RequestRelationAnalys request)
        {
            #region 
            var snPagelst = _inspectStandardRepository.GetTraceDtsByItemPagedList(request.setYProductCode, ProjectId, new List<int> { request.setYItem }, request.setStarttime, request.setEndtime, request.page, request.pageSize);
            if (!snPagelst.Data.Any())
                throw new BadRequestException(CommonEnum.RecordNotFound);

            var itemIds = request.setXItems;
            itemIds.Add(request.setYItem);
            var headroute = _inspectStandardRepository.GetSectionItem(ProjectId, request.setYItem, itemIds).OrderBy(o => o.Section).OrderByDescending(d=>d.sort).ToList();
            var dataArry = snPagelst.Data.OrderBy(o => o.Sn).ToList();
            var snArry = snPagelst.Data.Select(s => s.Sn).ToList();
            var sectionData = _inspectStandardRepository.GetTraceDtsByItem(request.setYProductCode, ProjectId, snArry, itemIds, request.setStarttime, request.setEndtime).ToList();
            var convertResult = GetReportFormat(dataArry, sectionData, headroute);
         
            var outPut = new List<BIAnalysStationUI>();
            var groupData = convertResult.Bodys.GroupBy(g => g.Row);
            foreach (var g in groupData)
            {
                outPut.Add(new  BIAnalysStationUI 
                {
                    RowNo = g.Key,
                    RowsCols = g.ToList()
                });
            }
            var result = new GeneralResponseBIResult
            {
                Heads = convertResult.Heads,
                Bodys = outPut
            };
            return new PagedObjectResult(result, snPagelst.Total, request.page, request.pageSize);
            #endregion
        }

        /// <summary>
        /// 标准检验项关联性分析-可视化
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetRelationVisualization([FromBody]RequestRelationAnalys request)
        {
           
            var result= RunPython(request);
            if(result==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (result.Activated == 0)
            {
                Logger.WriteLineInfo(result.Data.ToString());
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (!result.Ranking.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            Logger.WriteLineInfo($"python Response:{JsonConvert.SerializeObject(result)}");
            var rankingTotal = result.Ranking.Count();
            var top3Rankings = result.Ranking.Take(rankingTotal>=3?3:rankingTotal);
            var rankings = new List<RankingPic>();
         
            var top10item = new List<Top10Item>();

            var yItemData = _inspectStandardRepository.GetTraceDtsValByItem(request.setYProductCode, ProjectId, new List<int> { request.setYItem }, request.setStarttime, request.setEndtime).ToList();
            foreach (var r in top3Rankings)
            {
                var xId = r.ID.Replace("ID", "");
                var xItemData = _inspectStandardRepository.GetTraceDtsValByItem(request.setYProductCode, ProjectId, new List<int> { xId.ToInt() }, request.setStarttime, request.setEndtime).ToList();
                var yItemDts = yItemData.GroupBy(g => g.Sn).Select(s => s.LastOrDefault()).OrderBy(o=>o.Sn);
                var xItemDts = xItemData.GroupBy(g => g.Sn).Select(s => s.LastOrDefault()).OrderBy(o => o.Sn);
                var echart = new List<List<string>>();
                foreach (var yItm in yItemDts)
                {
                    foreach (var xVal in xItemDts)
                    {
                        if (yItm.Sn == xVal.Sn)
                        {
                            var xyVal = new List<string> { yItm.Value, xVal.Value };
                            echart.Add(xyVal);
                        }
                    }
                }
                var obj = _inspectStandardRepository.Get(f => f.id == xId.ToInt());
                rankings.Add(new RankingPic
                {
                    ID = xId,
                    Value = obj!=null? obj.item:"",
                    Echart = echart
                });
            }
           // var top10Rankings = result.Ranking.Take(rankingTotal >= 10 ? 10 : rankingTotal);
            foreach (var top in result.Ranking)
            {
                var xId = top.ID.Replace("ID", "");
                var obj = _inspectStandardRepository.Get(f => f.id == xId.ToInt());
                double.TryParse(top.Value.ToString(), out double val);
                top10item.Add(new Top10Item
                {
                    ItemId=xId.ToInt(),
                    Item=obj!=null?obj.item:"",
                    Value= val
                });
            }
            var output = new ResponseRelationAnalys
            {
                Summary = result.Summary,
                Rankings = rankings,
                Top = top10item
            };
            return new ObjectResult(output);
        }
        /// <summary>
        /// 分页数据拼接
        /// </summary>
        /// <param name="source"></param>
        /// <param name="xData"></param>
        /// <param name="router"></param>
        /// <returns></returns>
        ResponseBIResult GetReportFormat(List<ResponseTraceDts>source,List<ResponseTraceDts>xData,List<ResponseBiheadRoute>router)
        {
            var ret = new ResponseBIResult { Heads=new List<BIAnalysStation>(), Bodys=new List<BIAnalysStation>() };
            var row = 0;
            foreach (var d in source)
            {
                row += 1;
                var routeStation = router.GroupBy(g => g.Section);
                foreach(var rStation in routeStation)
                {
                    var curStation = rStation.FirstOrDefault();
                    var curStationData = rStation.ToList();
                    var head = new BIAnalysStation
                    {
                        Sn = "headSn",
                        Section = curStation.Section,
                        Station = curStation.SectionTitle,
                        Items = new List<OQCItemDts>()
                    };
                    var body = new BIAnalysStation
                    {
                        Row = row,
                        Sn = d.Sn,
                        Section = curStation.Section,
                        Station = curStation.SectionTitle,
                        Items = new List<OQCItemDts>()
                    };
                    foreach (var r in curStationData)
                    {
                        var stationItem = xData.Where(f => f.Section == rStation.Key && f.Sn == d.Sn && f.Item3 == r.ItemId).OrderByDescending(o => o.id);
                        if (!stationItem.Any())
                        {
                            head.Items.Add(new OQCItemDts
                            {
                                ItemId = r.ItemId,
                                Item = r.Item,
                                Value=""
                            });
                            body.Items.Add(new OQCItemDts
                            {
                                ItemId = r.ItemId,
                                Item = r.Item,
                                Value = "",
                            });
                        }
                        else
                        {
                            var lastObj = stationItem.FirstOrDefault();
                            head.Items.Add(new OQCItemDts
                            {
                                ItemId = lastObj.Item3,
                                Item = lastObj.Item,
                            });
                            body.Items.Add(new OQCItemDts
                            {
                                ItemId = lastObj.Item3,
                                Item = lastObj.Item,
                                Value = lastObj.Value,
                            });

                        }
                    }
                    if (!ret.Heads.Exists(f => f.Section == head.Section))
                    {
                        ret.Heads.Add(head);
                    }
                    ret.Bodys.Add(body);
                }
            }
            return ret;
        }

        QmsBI4Result RunPython(RequestRelationAnalys request)
        {
            var res = string.Empty;
            try
            {
                var interfaceName = "QMSRG";// EnumHelper.GetEnumDesc(QmsBIInterfaceType.RelationAnalysis);

                var fileSetting = Config<FileSettings>.Get();
                var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "PythonQMSBI");
               
                var pythonPath = ConfigManager.GetValue("PythonPathSetting", "PyPath", string.Empty);
                if (string.IsNullOrEmpty(pythonPath))
                {
                    throw new Exception("DbSetting about [PythonPathSetting] not found.");
                }
                var pythonScriptPath = $"{rootDir}/QMS_API.py";// $"{rootDir}/QmsBI.py";
                if (!System.IO.File.Exists(pythonScriptPath))
                {
                    throw new Exception($"QMS_API.py {rootDir} not found.");
                }
                var jsonstr = JsonConvert.SerializeObject(request);
                var BIHelper = new PythonBIHelper();
                res = BIHelper.RunRelationAnalysis(pythonPath, pythonScriptPath, interfaceName, request);
         
                if (string.IsNullOrEmpty(res))
                {
                    return null;
                }
                return JsonConvert.DeserializeObject<QmsBI4Result>(res);
            }
            catch (Exception ex)
            {
                Logger.WriteLineError($"pthonFeedback: {res} GetQmsBIChartError:" + ex);
                throw new Exception(ex.Message);
            }
        }
    }    
}