using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiDashboard.Result;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.DashboardRepository.Repositories.Interface;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;

namespace Siger.ApiDashboard.Controllers
{
    public class DashboardQmsController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ICheckSnTraceMaterialRepository _traceMaterialRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ICheckSnTraceInspectionRepository _traceInspectionRepository;
        private readonly Isiger_wms_bussinese_contactsRepository _businessRepository;
        private readonly ISigerAndonInfoRepository _andonInfoRepository;
        private readonly IQmsReworkDataRepository _reworkDataRepository;
        private readonly ISigerAndonExpectionTypeRepository _andonExpectionType;
        private readonly ISigerSystemConfigRepository _systemConfigRepository;
        private readonly IDashboardFactoryChanel _dashboardFactoryChanel;
        private readonly IDashboardLevelRepository _dashboardLevel;
        private readonly IInspectStandardRepository _standardRepository;
        private readonly ICheckSnTraceDetailRepository _traceDetailRepository;

        /// <inheritdoc />
        public DashboardQmsController(IUnitOfWork unitOfWork, 
            ICheckSnTraceMaterialRepository traceMaterialRepository, ISigerProjectLevelRepository levelRepository,
            ISigerProjectLevelSectionRepository levelSectionRepository, ICheckSnTraceInspectionRepository traceInspectionRepository,
            Isiger_wms_bussinese_contactsRepository businessRepository, ISigerAndonInfoRepository andonInfoRepository,
            IQmsReworkDataRepository reworkDataRepository, ISigerAndonExpectionTypeRepository andonExpectionRepository,
            ISigerSystemConfigRepository systemConfigRepository, IDashboardFactoryChanel dashboardFactory,
            IDashboardLevelRepository dashboardLevel, IInspectStandardRepository standardRepository, ICheckSnTraceDetailRepository traceDetailRepository)
        {
            _unitOfWork = unitOfWork;
            _traceMaterialRepository = traceMaterialRepository;
            _levelRepository = levelRepository;
            _levelSectionRepository = levelSectionRepository;
            _traceInspectionRepository = traceInspectionRepository;
            _businessRepository = businessRepository;
            _andonInfoRepository = andonInfoRepository;
            _reworkDataRepository = reworkDataRepository;
            _andonExpectionType = andonExpectionRepository;
            _systemConfigRepository = systemConfigRepository;
            _dashboardFactoryChanel = dashboardFactory;
            _dashboardLevel = dashboardLevel;
            _standardRepository = standardRepository;
            _traceDetailRepository = traceDetailRepository;
        }
        [HttpGet]
        public IActionResult GetIncomingCheckResult()
        {
            var res = new GetIncomingCheckResult();

            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = daterange.StarTime;
            var etime = daterange.EndTime;
            var data = _traceMaterialRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.CreateTime <= etime && t.CreateTime >= stime).ToList();
            if (!data.Any())
            {
                return new ObjectResult(res);
            }
            var total = (double)data.Sum(t => t.TotalQuantity);

            res.Qualified = data.Count(t => t.Result.ToInt() == (int)IncomingMaterialType.Qalified);
            res.QualifiedRate = Math.Round(res.Qualified / total, 4) * 100;
            res.Rework = data.Count(t => t.Result.ToInt() == (int)IncomingMaterialType.Rework);
            res.ReworkRate = Math.Round(res.Rework / total, 4) * 100;
            res.Reception = data.Count(t => t.Result.ToInt() == (int)IncomingMaterialType.ConcessionReception);
            res.ReceptionRate = Math.Round(res.Reception / total, 4) * 100;
            res.Rejection = data.Count(t => t.Result.ToInt() == (int)IncomingMaterialType.Rejection);
            res.RejectionRate = Math.Round(100 - res.QualifiedRate - res.ReworkRate - res.RejectionRate, 2);
            res.Total = res.Qualified + res.Reception;
            res.Defect = res.Rework + res.Rejection;
            res.TotalRate = Math.Round(res.Total / total, 4) * 100;
            res.DefectRate = Math.Round(100 - res.TotalRate, 2);

            var suppliers = _businessRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            data = data.Where(t => t.Result.ToInt() == (int)IncomingMaterialType.ConcessionReception).ToList();
            foreach (var item in data)
            {
                var supplier = suppliers.FirstOrDefault(t => t.id == item.SupplierID);
                if (supplier != null)
                {
                    res.details.Add(new SupplierDetail
                    {
                        name = supplier.name,
                        batchnumber = item.BatchNumber,
                        total = item.TotalQuantity,
                        random = item.RandomCheckNumber
                    });
                }
            }

            return new ObjectResult(res);
        }
        [HttpGet]
        public IActionResult GetCheckStationStatus(int type)
        {
            var lines = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            if (!lines.Any())
            {
                throw new BadRequestException(RequestEnum.LevelSectionNotFound);
            }
            var res = new GetCheckStationStatusResult();
            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = daterange.StarTime.ToString(ParameterConstant.DateTimeFormat);
            var etime = daterange.EndTime.ToString(ParameterConstant.DateTimeFormat);
            var data = _traceDetailRepository.GetSnTraceList(new List<int>(), 0, 0, type, stime, etime, ProjectId).ToList();
            var typeOne = type.ToString(); var typeEnd = $",{typeOne}"; var typeStart = $"{typeOne},"; var typeTwo = $",{typeOne},";//精确匹配，避免类似12匹配到1的情况
            var sectionIds = _standardRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                (t.checktype.Contains(",") ? (t.checktype.Contains(typeTwo) || t.checktype.StartsWith(typeStart) || t.checktype.EndsWith(typeEnd)) : (t.checktype == typeOne))).Select(t => t.sectionid).Distinct().ToList();
            var checkDatas = _traceInspectionRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.check_type == type && (t.send_time <= daterange.EndTime && t.send_time >= daterange.StarTime) ||
                (t.check_time <= daterange.EndTime && t.check_time >= daterange.StarTime) ||
                (t.recieve_time <= daterange.EndTime && t.recieve_time >= daterange.StarTime) ||
                (t.checking_time <= daterange.EndTime && t.checking_time >= daterange.StarTime)).ToList();
            foreach (var line in lines)
            {
                var channel = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == line.id);
                if (channel != null)
                {
                    var list = new List<CheckSectionStatus>();
                    var sections = GetSectionSelect(1, line.id).Where(t => sectionIds.Contains(t.id)).ToList();
                    foreach (var section in sections)
                    {
                        var sectionData = data.Where(t => t.SectionID == section.id);
                        var checkData = checkDatas.Where(t => t.sectionid == section.id);
                        var state = 1;
                        if (checkData.Any())
                        {
                            if (checkData.Any(t => t.check_status == (int)SendCheckStatus.Checking &&
                                t.checking_time <= daterange.EndTime && t.checking_time >= daterange.StarTime ||
                                t.check_status == (int)SendCheckStatus.Recieved &&
                                t.recieve_time <= daterange.EndTime && t.recieve_time >= daterange.StarTime ||
                                t.check_status == (int)SendCheckStatus.Testing &&
                                t.send_time <= daterange.EndTime && t.send_time >= daterange.StarTime))
                            {
                                state = 2;
                            }
                            else if (checkData.Any(t => t.result == ((int)SendTestType.Unqualified).ToString() &&
                                t.check_time <= daterange.EndTime && t.check_time >= daterange.StarTime) ||
                                sectionData.FirstOrDefault(t => t.Result.ToUpper() == "NG") != null)
                            {
                                state = 4;
                            }
                            else if (checkData.Any(t => t.result == ((int)SendTestType.DeviationRelease).ToString() &&
                                t.check_time <= daterange.EndTime && t.check_time >= daterange.StarTime))
                            {
                                state = 5;
                            }
                            else if(!checkData.Any(t => (t.result == ((int)SendTestType.Qalified).ToString() ||
                                t.result == ((int)SendTestType.DeviationRelease).ToString()) &&
                                t.check_time <= daterange.EndTime && t.check_time >= daterange.StarTime) ||
                                sectionData.FirstOrDefault(t => t.Result.ToUpper() == "OK") != null)
                            {
                                state = 3;
                            }
                            else if (checkData.Any(t => t.check_status == (int)SendCheckStatus.Testing ||
                                t.check_status == (int)SendCheckStatus.Recieved))
                            {
                                state = 1;
                            }
                        }
                        else if(sectionData.Any())
                        {
                            state = sectionData.FirstOrDefault(t => t.Result.ToUpper() == "NG") != null ? 4 : 3;
                        }
                        list.Add(new CheckSectionStatus
                        {
                            section = section.name,
                            status = state//1未检验 2检验中 3合格 4不合格 5让步接收 
                            //优先级 检验中 不合格 让步接收 合格 未检验
                        });
                    }
                    res.data.Add(new CheckStationList
                    {
                        Channel = channel.title,
                        CheckSections = list
                    });
                }
            }
            return res;
        }

        private List<ResponseIdName> GetSectionSelect(int reverselevel, int parentid)
        {
            var levels = _levelRepository.GetList(t => t.status == (int)RowState.Valid &&
                t.projectid == ProjectId).OrderByDescending(t => t.id).ToList();
            if (levels.Count < reverselevel)
            {
                throw new BadRequestException(RequestEnum.LevelNotFound);
            }
            var res = _levelSectionRepository.GetSectionIdNamesByLevel(levels[reverselevel - 1].id,
                    parentid, ProjectId).ToList();
            return res;
        }

        [HttpGet]
        public IActionResult GetTestRoomCheckStatus()
        {
            var res = new GetTestRoomCheckStatusResult();

            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = daterange.StarTime;
            var etime = daterange.EndTime;
            var data = _traceInspectionRepository.GetList(t => t.projectid == ProjectId &&
                t.status == (int)RowState.Valid && t.send_time <= etime && t.send_time >= stime && t.inspection_type == 1).ToList();
            var total = (double)data.Sum(q => q.number);
            res.Qualified = data.Where(t => t.result.ToInt() == (int)SendTestType.Qalified).Sum(q => q.number);
            res.QualifiedRate = total > 0 ? Math.Round(res.Qualified / total, 4) * 100 : 100;
            res.DeviationRelease = data.Where(t => t.result.ToInt() == (int)SendTestType.DeviationRelease).Sum(q => q.number);
            res.DeviationReleaseRate = total > 0 ? Math.Round(res.DeviationRelease / total, 4) * 100 : 0;
            res.UnQualified = data.Where(t => t.result.ToInt() == (int)SendTestType.Unqualified).Sum(q => q.number);
            res.UnQualifiedRate = total > 0 ? Math.Round(100 - res.QualifiedRate - res.DeviationReleaseRate, 2) : 0;
            
            res.Compeleted = data.Where(t => t.check_status == (int)SendCheckStatus.Completed).Sum(q => q.number);
            res.Testing = data.Where(t => t.check_status == (int)SendCheckStatus.Testing).Sum(q => q.number);
            res.Recieved = data.Where(t => t.check_status == (int)SendCheckStatus.Recieved).Sum(q => q.number);
            res.Checking = data.Where(t => t.check_status == (int)SendCheckStatus.Checking).Sum(q => q.number);
            var total1 = res.Compeleted + res.Testing;
            res.CompeletedRate = total1 > 0 ? Math.Round(res.Compeleted / total, 4) * 100 : 0;
            res.RecievedRate = total1 > 0 ? Math.Round(res.Recieved / total, 4) * 100 : 0;
            res.CheckingRate = total1 > 0 ? Math.Round(res.Checking / total, 4) * 100 : 0;
            res.TestingRate = total1 > 0 ? Math.Round(100 - res.CompeletedRate - res.RecievedRate - res.CheckingRate, 2) : 0;

            return new ObjectResult(res);
        }

        /// <summary>
        /// ftq良率 分通道显示
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetChannelFtq(int section, string date)
        {
            var lines = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            if (!lines.Any())
            {
                throw new BadRequestException(RequestEnum.LevelSectionNotFound);
            }
            var res = new GetChannelFtqResult();
            var _yieldRepository = new LocationYieldRepository(CompanyId, ProjectId);
            var daterange = DateTimeHelper.GetDateTimeRange(date);
            var stime = daterange.StarTime;
            var etime = daterange.EndTime;
            var lstSections = new List<int> { };
            if (section != 0)
            {
                var stations = _levelSectionRepository.GetAccStationByline(ProjectId, section).Select(s => s.id).ToList();
                lstSections.AddRange(stations);
                lines = lines.Where(f => f.id == section);
            }
            var data = _traceDetailRepository.GetSnTraceList(lstSections, 0, 0, 0, stime.ToString(ParameterConstant.DateTimeFormat), etime.ToString(ParameterConstant.DateTimeFormat), ProjectId).ToList();

            var stationLow = new List<LineFtqObj>();
            var ychart = new double[] { 98.92 , 87.9 , 99.45 , 100 , 96.11 };
            var i = 0;
            foreach (var line in lines)
            {
                var channel = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == line.id);
                if (channel != null)
                {
                    res.X.Add(channel.title);
                    
                    res.Y.Add(ychart[i]);
                    i++;
                }
            }
            res.totalFtq = 99.78;

            return new ObjectResult(res);
        }

        /// <summary>
        /// ftq良率 分通道显示
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetQmsChannelFtq()
        {
            var lines = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            if (!lines.Any())
            {
                throw new BadRequestException(RequestEnum.LevelSectionNotFound);
            }
            var res = new GetChannelFtqResult();
            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = daterange.StarTime.ToString(ParameterConstant.DateTimeFormat);
            var etime = daterange.EndTime.ToString(ParameterConstant.DateTimeFormat);

            var _yieldRepository = new LocationYieldRepository(CompanyId, ProjectId);

            var data = _traceDetailRepository.GetSnTraceList(new List<int> { }, 0, 0, 0, stime.ToString(), etime.ToString(), ProjectId).ToList();
            var yieldCount = 0;
            var recordCount = 0d;
            foreach (var line in lines)
            {
                var channel = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == line.id);
                if (channel != null)
                {
                    var sections = GetSectionSelect(1, line.id);
                    var yieldDatas = _yieldRepository.GetLocationYieldsBySectionIds(sections.Select(t => t.id), stime.ToDateTime(), 
                        etime.ToDateTime()).ToList();
                    res.X.Add(channel.title);
                    var list = data.Where(t => sections.Select(q => q.id).Contains(t.SectionID)).ToList();
                    double okRate = 1;

                    var bottleMachines = _dashboardLevel.GetBottleSection(sections.Select(s => s.id).ToList(), ProjectId, false).ToList();
                    var yield = yieldDatas.Where(t => bottleMachines.Contains(t.sectionID)).Sum(t => t.yield);
                    foreach (var section in sections)
                    {
                        var ngNum = list.Count(t => t.SectionID == section.id && t.Result.ToUpper() == "NG");
                      //  var yield = yieldDatas.Where(t => t.sectionID == section.id).Sum(t => t.yield);
                        if (yield > 0)
                        {
                            var actualYield = (yield - ngNum) > 0 ? (yield - ngNum) : 0;
                            var rate = yield > 0 ? actualYield / (double)yield : 0;
                            if (rate < okRate)
                            {
                                okRate = rate;
                            }
                            yieldCount += actualYield;
                            recordCount += yield;
                        }
                    }
                    res.Y.Add(Math.Round((okRate > 1 ? 1 : okRate) * 100, 2));
                }
            }
            if (recordCount > 0d)
            {
                var rateTotal = yieldCount / recordCount;
                res.totalFtq = Math.Round((rateTotal > 1 ? 1 : rateTotal) * 100, 2);
            }
            return new ObjectResult(res);
        }

        /// <summary>
        /// 获取安灯数量
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetFailureData()
        {
            var lines = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            if (!lines.Any())
            {
                throw new BadRequestException(RequestEnum.LevelSectionNotFound);
            }
            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = UnixTimeHelper.ConvertDataTimeLong(daterange.StarTime);
            var etime = UnixTimeHelper.ConvertDataTimeLong(daterange.EndTime);
            var res = new GetFailureDataResult();
            var config = _systemConfigRepository.Get(t => t.status == (int)RowState.Valid && t.key == SystemConfigKey.QmsAndenException);
            var configValue = config?.value ?? "";
            var exceptionList = _andonExpectionType.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.name == configValue && t.level == 1).ToList();
            var exceptionIds = new List<int>();
            exceptionIds = exceptionList.Select(t => t.id).ToList();
            foreach (var exception in exceptionList)
            {
                exceptionIds.AddRange(_andonExpectionType.GetExpectionSonLevel(exception.id, ProjectId).Select(t => t.id).ToList());
            }
            var data = _andonInfoRepository.GetList(t => t.projectid == ProjectId && t.status != (int)RowState.Invalid &&
                exceptionIds.Contains(t.expection_type) && t.status > (int)AndonState.Abnormal && t.status < (int)AndonState.CancleAbnormal &&
                t.create_time >= stime && t.create_time <= etime).ToList();
            //var lines = GetSectionSelect(2, 0);            
            res.total = data.Count;
            res.unhandle = data.Count(t => t.status == (int)AndonState.WaitHandle);
            res.handling = data.Count(t => t.status == (int)AndonState.Handling);
            res.handle = data.Count(t => t.status == (int)AndonState.Complete);
            foreach (var line in lines)
            {
                var channel = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == line.id);
                if (channel != null)
                {
                    var sections = GetSectionSelect(1, line.id);
                    var list = data.Where(t => sections.Select(q => q.id).Contains(t.station)).ToList();
                    res.X.Add(channel.title);
                    var unhandle = list.Count(t => t.status == (int)AndonState.WaitHandle);
                    res.unhandles.Add(unhandle);
                    var handling = list.Count(t => t.status == (int)AndonState.Handling);
                    res.handlings.Add(handling);
                    var handle = list.Count(t => t.status == (int)AndonState.Complete);
                    res.handles.Add(handle);
                }
            }

            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult GetScrapData()
        {
            var lines = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            if (!lines.Any())
            {
                throw new BadRequestException(RequestEnum.LevelSectionNotFound);
            }
            var res = new GetChannelFtqResult();

            var daterange = DateTimeHelper.GetDateTimeRange(DateTime.Now.ToString());
            var stime = daterange.StarTime;
            var etime = daterange.EndTime;
            var data = _reworkDataRepository.GetList(t => t.projectid == ProjectId &&
                t.Type == (int)ReworkDataType.Waste && t.DateTime <= etime && t.DateTime >= stime).ToList();
            foreach (var line in lines)
            {
                var channel = _levelSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == line.id);
                if (channel != null)
                {
                    var sections = GetSectionSelect(1, line.id);
                    var list = data.Where(t => sections.Select(q => q.id).Contains(t.Route_Id)).ToList();
                    res.X.Add(channel.title);
                    res.Y.Add(list.Sum(t => t.Count));
                }
            }

            return new ObjectResult(res);
        }
    }
}