using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Request;
using Siger.Middlelayer.CncRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.Dapper.Utilities.Slice;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Log;

namespace Siger.ApiCNC.Controllers
{
    public class WorkingStateController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IWorkingStateRepository _stateRepository;
        private readonly IMachineCurrentStateRepository _currentStateRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly IWorkingSignRepository _workingSignRepository;
        private readonly ISigerProjectUserRepository _projectUserRepository;
        private readonly IWorkingGroupRepository _workingGroupRepository;
        //private readonly IWorkingMachineSetRepository _workingMachineSetRepository;
        private readonly IProductPlanRepository _productPlanRepository;
        private readonly IProductPlanDetailRepository _productPlanDetailRepository;
        private readonly IProduceScheduleRepository _produceScheduleRepository;
        private readonly ISigerProjectProductReport _projectProductReport;
        private readonly ISigerProjectProductRepository _productRepository;
        private readonly IProductRouteRepository _routeRepository;
        private readonly IWorkingRelationMachineRepository _workingRelationMachine;
        private readonly IWorkingRelationUserRepository _workingRelationUser;

        public WorkingStateController(IUnitOfWork unitOfWork ,IWorkingStateRepository stateRepository, IMachineCurrentStateRepository currentStateRepository,
            ISigerProjectMachineRepository machineRepository, ISigerProjectLevelSectionRepository levelSectionRepository, 
            IWorkingSignRepository workingSignRepository, ISigerProjectUserRepository projectUserRepository, IWorkingGroupRepository workingGroupRepository,
            IProductPlanRepository productPlanRepository, IProductPlanDetailRepository productPlanDetailRepository,
            IProduceScheduleRepository produceScheduleRepository, ISigerProjectProductReport projectProductReport, ISigerProjectProductRepository productRepository,
            IProductRouteRepository routeRepository,IWorkingRelationMachineRepository workingRelationMachine,IWorkingRelationUserRepository workingRelationUser)
        {
            _unitOfWork = unitOfWork;
            _stateRepository = stateRepository;
            _currentStateRepository = currentStateRepository;
            _machineRepository = machineRepository;
            _levelSectionRepository = levelSectionRepository;
            _workingSignRepository = workingSignRepository;
            _projectUserRepository = projectUserRepository;
            _workingGroupRepository = workingGroupRepository;
            //_workingMachineSetRepository = workingMachineSetRepository;
            _productPlanRepository = productPlanRepository;
            _productPlanDetailRepository = productPlanDetailRepository;
            _produceScheduleRepository = produceScheduleRepository;
            _projectProductReport = projectProductReport;
            _productRepository = productRepository;
            _routeRepository = routeRepository;
            _workingRelationMachine = workingRelationMachine;
            _workingRelationUser = workingRelationUser;
        }

        [HttpGet]
        public IActionResult GetAllState()
        {
            var query = _stateRepository.GetList(q => q.project_id == ProjectId && q.status == (int) RowState.Valid)
                .Select(m => new ResponseIdTitle
                {
                    id = m.state_code.ToInt(),
                    title = m.state_name
                }).ToList();
            return new ObjectResult(query);
        }

        /// <summary>
        /// 设备节拍分析
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult MachineBeatAnalysis(string levelId, string timerange, string workgroupId, string userId)
        {
            var times = timerange.Split(" - ");
            var success = DateTime.TryParse(times[0], out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(times[1], out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var start = times[0];
            var end = dtEnd.AddDays(1).AddMilliseconds(-1) > DateTime.Now
                ? DateTime.Now.ToString(ParameterConstant.DateTimeFormat)
                : dtEnd.AddDays(1).AddMilliseconds(-1).ToString(ParameterConstant.DateTimeFormat);
            var responses = new List<MachineBeatAnalysis>();
            var datas = _currentStateRepository.GetMachineBeatAnalysis(levelId.ToInt(), timerange, workgroupId.ToInt(),
                userId.ToInt(), ProjectId);
            if (!datas.Any())
            {
                return new ObjectResult(responses);
            }
            var validMachines = _machineRepository.GetNCLevelSectionNames(levelId.ToInt(), ProjectId);
            var machineIds = validMachines.Select(m => m.machine_id).Distinct();
            var sliceRepositoey = new SliceSateRepository(CompanyId, ProjectId);
            var sliceSates = sliceRepositoey.GetCncSliceSates(machineIds, start, end);
            var yieldRepository = new ProductRepository(CompanyId, ProjectId);
            var yields = yieldRepository.GetYileds(start, end, machineIds);
            foreach (var analysis in datas)
            {
                var entity = Mapper<ResponseMachineBeatAnalysis, MachineBeatAnalysis>.Map(analysis);
                var section = validMachines.FirstOrDefault(q => q.machine_id == analysis.machine_id);
                if (section != null)
                {
                    entity.location = section.lastSecondSectionTitle + "-" + section.lastSectionTitle;
                }

                var stateEnd = analysis.end ?? DateTime.Now;
                var machineYield = yields.Where(q => q.machineID == analysis.machine_id && q.dataTime >= analysis.start && q.dataTime <= stateEnd);
                if (machineYield.Any())
                {
                    var dayStatus = SliceManager.GetMachineStatusHold(new List<int> { analysis.machine_id },
                        analysis.start, stateEnd, sliceSates);
                    if (dayStatus == null || !dayStatus.Any())
                    {
                        responses.Add(entity);
                        continue;
                    }

                    var totalYield = machineYield.Sum(m => m.yield);
                    //实际生产节拍
                    entity.actual_beat = totalYield == 0 ? 0 : Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Running).TimeSpan / totalYield ,1);
                    //实际上下料节拍
                    entity.actual_updown = totalYield == 0 ? 0 : Math.Round(dayStatus.First(m => m.Status == MachineRunningStatus.Free).TimeSpan / totalYield, 1);
                }
                responses.Add(entity);
            }
            return new ObjectResult(responses);
        }

        /// <summary>
        /// 状态记录表
        /// </summary>
        [HttpGet]
        public IActionResult MachineStateRecord(string timerange, string sectionId, string workgroupId, string userId, int state = 0,
            int page = PageIndex, int pagesize = PageSize, int toexcel = 0)
        {
            var data = _currentStateRepository.GetPagedCollectionResult(timerange, sectionId.ToInt(),
                workgroupId.ToInt(), userId.ToInt(),  ProjectId, state, page, pagesize, toexcel);

            var list = new List<ResponseMachineStateRecord>();
            if (data.Total > 0)
            {
                var validMachines = _machineRepository.GetNCLevelSectionNames(0, ProjectId);
                foreach (var record in data.Data)
                {
                    var entity = Mapper<ResponseMachineStateRecord, ResponseMachineStateRecord>.Map(record);
                    var section = validMachines.FirstOrDefault(q => q.machine_id == record.machine_id);
                    if (section != null)
                    {
                        entity.location = section.lastSecondSectionTitle + "-" + section.lastSectionTitle;
                    }

                    var end = record.end == DateTime.MinValue ? DateTime.Now : record.end;
                    entity.seconds = (int)end.Subtract(entity.start).TotalSeconds;
                    list.Add(entity);
                }
            }
           
            if (toexcel == 0)
            {
                return new PagedObjectResult(list, data.Total, page, pagesize);
            }
            return ExportRecords(list);
        }

        [HttpPost]
        private IActionResult ExportRecords(IList<ResponseMachineStateRecord> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"MachineStateRecord_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<MachineStateRecordList>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<MachineStateRecordList>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new MachineStateRecordList
                    {
                        No = index,
                        Location = yield.location,
                        StateName = yield.location,
                        ProductName = yield.product_name,
                        SectionName = yield.section_name,
                        WorkGroupName = yield.workgroup_name,
                        UserName = yield.user_name,
                        StartTime = yield.start_time,
                        EndTime = yield.end_time,
                        TotalTimes = Math.Round((yield.end == DateTime.MinValue ? DateTime.Now : yield.end).Subtract(yield.start).TotalSeconds / 3600 , 1).ToStr()
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

                helper.GenerateExcel(machineYields, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportMachine state failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        /// <summary>
        /// 状态分析
        /// </summary>
        [HttpPost]
        public IActionResult MachineStateAnalysis([FromBody]RequestMachineStateAnalysis request)
        {
            var userIds = new List<int>();
            if (request.user_mid.ToInt() != 0)
            {
                userIds.Add(request.user_mid.ToInt());
            }
            else if(request.workgroup_id.ToInt() != 0)
            {
                var workingGroup = _workingGroupRepository.Get(q => q.id == request.workgroup_id.ToInt() && q.project_id == ProjectId && q.status == (int) RowState.Valid);
                if (workingGroup != null && workingGroup.user_mids.Any())
                {
                    workingGroup.user_mids.Split(',').ToList().ForEach(m =>
                    {
                        userIds.Add(m.ToInt());
                    });
                }
            }
            else if (request.section_id.ToInt() != 0)
            {
                userIds = _projectUserRepository.GetList(q =>
                    q.sectionid == request.section_id.ToInt() && q.projectid == ProjectId &&
                    q.status == (int) RowState.Valid).Select(m => m.mid).ToList();
            }
            else
            {
                userIds = null;
            }

            var times = request.time_range.Split(" - ");
            var success = DateTime.TryParse(times[0], out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(times[1], out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }
            dtEnd = dtEnd.AddDays(1).AddSeconds(-1);
            dtEnd = dtEnd > DateTime.Now ? DateTime.Now : dtEnd;
            if (dtStart > dtEnd)
            {
                throw new ServerException(100158);
            }

            var machinIds = _machineRepository.GetNCLevelSectionMachineIds(request.level_id.ToInt(), ProjectId);
            var states = _currentStateRepository.GetCurrentStates(machinIds, request.time_range, userIds, request.state,  ProjectId);
            if (!states.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var xid = request.x_id.ToInt();
            var responses = new List<ResponseKeyValue>();
            if (request.xtype == 1) //状态类型
            {
                var stateSets = _stateRepository.GetList(q => q.project_id == ProjectId && q.status == (int) RowState.Valid).ToList();
                var allStates = states.Select(m => m.machine_state).Distinct();
                foreach (var state in allStates)
                {
                    var set = stateSets.FirstOrDefault(q => q.state_code == state.ToString());
                    if(set == null) continue;
                    var stateDatas = states.Where(q => q.machine_state == state);
                    var total = stateDatas.Sum(data => data.end_time.Subtract(data.start_time).TotalSeconds);
                    responses.Add(new ResponseKeyValue(set.state_name, total.ToStr()));
                }
            }
            if (request.xtype == 2) //时间周期
            {
                var interal = DateTimeHelper.GetInteral(xid);
                var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, xid);

                for (var i = 0; i < dates.Count; i++)
                {
                    DateTime start;
                    DateTime end;
                    if (xid == 0 || xid == 1)
                    {
                        start = dates[i];
                        end = dates[i].AddDays(interal).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(interal).AddSeconds(-1);

                        var datas = states.Where(m => (m.start_time >= start && m.start_time <= end) || (m.end_time >= start && m.end_time <= end));
                        double total = 0;
                        foreach (var data in datas)
                        {
                            if (data.start_time >= start && data.end_time <= end)
                            {
                                total += data.end_time.Subtract(data.start_time).TotalSeconds;
                            }
                            else if (data.start_time >= start && data.end_time >= end)
                            {
                                total += end.Subtract(data.start_time).TotalSeconds;
                            }
                            else if (data.start_time <= start && data.end_time <= end)
                            {
                                total += data.end_time.Subtract(start).TotalSeconds;
                            }
                            else if (data.start_time <= start && data.end_time >= end)
                            {
                                total += end.Subtract(start).TotalSeconds;
                            }
                        }
                        responses.Add(new ResponseKeyValue(start.ToString(ParameterConstant.DateFormat),total.ToStr()));
                    }
                    else
                    {
                        start = dates[i].AddDays(1 - dates[i].Day);
                        end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                        var datas = states.Where(m => m.start_time >= start && m.end_time <= end);
                        responses.Add(new ResponseKeyValue(start.ToString("yyyy-MM"), 
                            datas.Sum(data => data.end_time.Subtract(data.start_time).TotalSeconds).ToStr()));
                    }
                }
            }
            if (request.xtype == 3) //产线层级
            {
                try
                {
                    var sections = _machineRepository.GetNCLevelSections(request.level_id.ToInt(), ProjectId);
                    var levels = sections.Where(q => q.levelid == xid).ToList();
                    if (levels.Any())
                    {
                        foreach (var levelSection in levels)
                        {
                            var machines = _machineRepository.GetNCLevelSectionMachineIds(levelSection.id, ProjectId);
                            if (!machines.Any())
                            {
                                continue;
                            }
                            var response = new ResponseKeyValue(levelSection.title, "0");
                            var datas = states.Where(m => machines.Contains(m.machine_id));
                            response.value = datas.Sum(data => data.end_time.Subtract(data.start_time).TotalSeconds).ToStr();
                            responses.Add(response);
                        }
                    }
                    else //选到最后一级的情况
                    {
                        if (sections.Any())
                        {
                            var section = sections.First();
                            var machines = _machineRepository.GetNCLevelSectionMachineIds(section.id, ProjectId);
                            if (machines.Any())
                            {
                                var response = new ResponseKeyValue(section.title, "0");
                                var datas = states.Where(m => machines.Contains(m.machine_id));
                                response.value = datas.Sum(data => data.end_time.Subtract(data.start_time).TotalSeconds).ToStr();
                                responses.Add(response);
                            }
                        }
                    }
                }
                catch
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
            }
            if (request.xtype == 4) //班组
            {
                var workGroups = _workingGroupRepository.GetList(q => q.project_id == ProjectId && q.status == (int)RowState.Valid).ToList();
                var allGroups = states.Select(m => m.workgroup_id).Distinct();
                foreach (var group in allGroups)
                {
                    var set = workGroups.FirstOrDefault(q => q.id == group);
                    if (set == null) continue;
                    var stateDatas = states.Where(q => q.workgroup_id == group);
                    var total = stateDatas.Sum(data => data.end_time.Subtract(data.start_time).TotalSeconds);
                    responses.Add(new ResponseKeyValue(set.name, total.ToStr()));
                }
            }

            if (request.toexcel == 0)
            {
                return new ObjectResult(responses);
            }

            return ExportStateAnalysis(responses);
        }


        [HttpPost]
        private IActionResult ExportStateAnalysis(IList<ResponseKeyValue> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"MachineStateAnalysis_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<ChartList>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<ChartList>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new ChartList
                    {
                        No = index,
                        X = yield.key,
                        Y = yield.value
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

                helper.GenerateExcel(machineYields, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export State Analysis failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }


        /// <summary>
        /// APP扫码
        /// </summary>
        /// <param name="machineid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetMachineState(string machineid)
        {
            var machineId = machineid.ToInt();
            var machine = _machineRepository.Get(t =>
                t.id == machineId && t.projectid == ProjectId && t.status == (int)RowState.Valid);
            if (machine == null)
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }

            var location = _machineRepository.GetMachineLocationByMachineId(machineId, ProjectId);

            var time = DateTime.Now;
            var currentMachineState = 0;
            double totalTime = 0;
            var currentMachine = _currentStateRepository.Get(t =>
                t.machine_id == machineId && t.project_id == ProjectId && t.status == (int)RowState.Valid && t.end_time == DateTime.MinValue);
            if (currentMachine != null)
            {
                currentMachineState = currentMachine.machine_state;
                totalTime = Math.Round((time - currentMachine.start_time).TotalSeconds);
            }

            var responsor = "";
            var sign = _workingSignRepository.Get(t => t.machine_id == machineId && t.project_id == ProjectId && t.status == (int)RowState.Valid && t.sign_outtime == DateTime.MinValue);
            if (sign != null)
            {
                responsor = _projectUserRepository.Get(t => t.status == (int)RowState.Valid && t.projectid == ProjectId && t.mid == UserId)?.name ?? "";
            }


            var machineStates = _stateRepository.GetList(q => q.project_id == ProjectId && q.status == (int)RowState.Valid).ToList();
            var machineOptionStates = new List<MachineOptionState>();
            foreach (var state in machineStates)
            {
                var type = 0;
                if(state.state_code.ToInt() == currentMachineState)
                {
                    type = currentMachine == null ? 1 : 2;
                }
                else
                {
                    type = 1;
                }

                machineOptionStates.Add(new MachineOptionState
                {
                    state = state.state_code.ToInt(),
                    nomal = state.state_type > 0 ? 0 : 1,
                    name = state.state_name,
                    type = type
                });
            }

            var statename = machineStates.FirstOrDefault(t => t.state_code == currentMachineState.ToString())?.state_name ?? "";
            var res = new ResponseGetMachineState
            {
                machineid = machineId,
                currentstate = currentMachineState,
                statename = statename,
                location = location,
                totaltime = totalTime,
                MachineStates = machineOptionStates,
                username = responsor
            };

            return new ObjectResult(res);
        }

        /// <summary>
        /// APP修改设备状态
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ModifyMachineState([FromBody]RequestModifyMachineState req)
        {
            var machine = _machineRepository.Get(t =>
                t.id == req.machineid && t.projectid == ProjectId && t.status == (int)RowState.Valid);
            if (machine == null)
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }

            var currentStates = _currentStateRepository.GetList(t => t.machine_id == req.machineid && t.project_id == ProjectId && 
                t.status == (int)RowState.Valid && t.end_time == DateTime.MinValue).ToList();
            var currentState = currentStates.FirstOrDefault(t => t.machine_state == req.state);
            if (req.type == 1)
            {
                if (currentState != null)
                {
                    throw new BadRequestException(RequestEnum.MachineStateHasStarted);
                }
            }
            if (req.type == 2)
            {
                if (currentStates.Any() && currentState == null)
                {
                    throw new BadRequestException(RequestEnum.MachineStateNotStarted);
                }
            }
            
            if (req.type == 1)
            {
                //var section = _machineRepository.GetSectionByMachineId(req.machineid, ProjectId);
                //var sectionId = section?.id ?? 0;
                //var machineSet = sectionId > 0 ? _workingMachineSetRepository.Get(t =>
                //    t.machine_id == sectionId && t.user_mid == UserId && t.project_id == ProjectId &&
                //    t.status == (int)RowState.Valid) : new siger_project_working_machine_set();

                var machineRelation = _workingRelationMachine.Get(f => f.machine == req.machineid && f.employsSplit.Contains(UserId));
                var groupId = machineRelation?.workgroup_id ?? 0;

                //var groupId = machineSet?.workinggroup_id ?? 0;
                //var state = _stateRepository.Get(t => t.project_id == ProjectId && t.status == (int)RowState.Valid && 
                //        t.state_code.ToInt() == req.state);
                //if (state != null && state.state_type == 0)
                //{
                //    if (string.IsNullOrEmpty(req.ordernumber))
                //    {
                //        throw new BadRequestException(RequestEnum.WorkOrderIsEmpty);
                //    }
                //    else
                //    {
                //        var order = _productPlanDetailRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                //                t.orderNumber == req.ordernumber);
                //        if(order == null)
                //        {
                //            throw new BadRequestException(RequestEnum.WorkOrderIsNotExist);
                //        }
                //    }
                //}
                foreach (var current in currentStates)
                {
                    current.end_time = DateTime.Now;
                    _currentStateRepository.Update(current);
                }
                var entity = new siger_project_working_machine_current_state
                {
                    machine_id = req.machineid,
                    machine_state = req.state,
                    project_id = ProjectId,
                    start_time = DateTime.Now,
                    end_time = DateTime.MinValue,
                    user_mid = UserId,
                    product_id = req.productid.ToInt(),
                    route_name = req.routename ?? "",
                    order_number = req.ordernumber ?? "",
                    workgroup_id = groupId
                };
                _currentStateRepository.Insert(entity);
            }
            else if (currentState != null && req.type == 2)
            {
                currentState.end_time = DateTime.Now;
                _currentStateRepository.Update(currentState);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// APP扫码工单
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetProductionInfo([FromBody]RequestGetProductionInfo req)
        {
            var res = new ResponseGetProductionInfo();

            var machine = _machineRepository.Get(t =>
                    t.id == req.machineid.ToInt() && t.projectid == ProjectId && t.status == (int)RowState.Valid);
            if (machine == null)
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }

            var responsor = "";
            var sign = _workingSignRepository.Get(t => t.machine_id == req.machineid.ToInt() && t.project_id == ProjectId &&
                    t.status == (int)RowState.Valid && t.sign_outtime == DateTime.MinValue);
            if (sign != null)
            {
                responsor = _projectUserRepository.Get(t => t.status == (int)RowState.Valid && t.projectid == ProjectId
                        && t.mid == UserId)?.name ?? "";
            }

            var state = _stateRepository.Get(t => t.project_id == ProjectId && t.status == (int)RowState.Valid &&
                    t.state_type == 0);
            if(state != null)
            {
                var currentState = _currentStateRepository.Get(t => t.project_id == ProjectId && t.status == (int)RowState.Valid &&
                        t.machine_id == req.machineid.ToInt() && state.state_code.ToInt() == t.machine_state && t.end_time == DateTime.MinValue);
                if (currentState != null)
                {
                    var proudct = _productRepository.Get(t => t.id == currentState.product_id && t.status == (int)RowState.Valid && t.projectid == ProjectId);
                    res = new ResponseGetProductionInfo
                    {
                        drawno = proudct?.drawingcode ?? "",
                        productname = proudct?.name ?? "",
                        productid = currentState.product_id,
                        productcode = proudct?.code ?? "",
                        ordernumber = currentState.order_number,
                        routes = new List<string> { currentState.route_name ?? "" },
                        username = responsor,
                        type = 1
                    };
                    return new ObjectResult(res);
                }
            }

            if (string.IsNullOrEmpty(req.ordernumber))
            {
                res.products = GetProducts();
                return new ObjectResult(res);
            }

            var reports = _produceScheduleRepository.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                    t.sectionId == req.machineid.ToInt()).ToList();
            var planDetailIds = reports.Select(t => t.plandetail_id).ToList();
            var orderDetails = _productPlanDetailRepository.GetList(t => planDetailIds.Contains(t.id) && 
                    t.orderNumber == req.ordernumber && t.projectId == ProjectId && t.status == (int)RowState.Valid).ToList();
            var planId = orderDetails.FirstOrDefault()?.planId ?? 0;
            var order = _productPlanRepository.Get(t =>
                    t.id == planId && t.projectid == ProjectId && t.status > (int)RowState.Invalid);
            if (!orderDetails.Any() || order == null)
            {
                var backet = _stateRepository.GetBasketlist(req.ordernumber, ProjectId).FirstOrDefault();
                if (backet == null)
                {
                    res.type = 0;
                    res.products = GetProducts();
                    return new ObjectResult(res);
                }
                var product = _productRepository.Get(t => t.code == backet.PrdNumber && t.status == (int)RowState.Valid && t.projectid == ProjectId);
                if (product == null)
                {
                    res.type = 0;
                    res.products = GetProducts();
                    return new ObjectResult(res);
                }
                var routes = _routeRepository.GetList(t => t.productId == product.id && t.projectId == ProjectId &&
                                                           t.status == (int)RowState.Valid).ToList();
                res = new ResponseGetProductionInfo
                {
                    drawno = product.drawingcode,
                    productname = product.name,
                    productid = product.id,
                    productcode = product.code,
                    ordernumber = req.ordernumber,
                    routes = routes.Select(t => t.name).ToList(),
                    username = responsor,
                    type = 1
                };
            }
            else
            {
                var planDetialIds = orderDetails.Select(t => t.id).ToList();
                var schedules = _produceScheduleRepository.GetList(t =>
                        planDetialIds.Contains(t.plandetail_id) && t.projectId == ProjectId && t.status == (int)RowState.Valid).ToList();

                res = new ResponseGetProductionInfo
                {
                    drawno = order.draw_number,
                    productname = order.product_name,
                    productid = order.product_id,
                    productcode = order.product_code,
                    ordernumber = req.ordernumber,
                    routes = schedules.Select(t => t.route_name).ToList(),
                    username = responsor,
                    type = 1
                };
            }

            if(res.productid == 0 && !res.products.Any())
            {
                res.type = 0;
                res.products = GetProducts();
                return new ObjectResult(res);
            }
            return new ObjectResult(res);
        }

        private List<MachineStateProduct> GetProducts()
        {
            var products = new List<MachineStateProduct>();
            var product = _productRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            foreach (var p in product)
            {
                var pro = new MachineStateProduct
                {
                    productcode = p.code,
                    productid = p.id,
                    productname = p.name,
                    drawno = p.drawingcode
                };
                var routes = _routeRepository.GetList(t => t.productId == p.id && t.projectId == ProjectId &&
                        t.status == (int)RowState.Valid).ToList();
                pro.routes = routes.Select(t => t.name).ToList();
                products.Add(pro);
            }
            return products;
        }

        /// <summary>
        /// 调产状态统计
        /// </summary>
        /// <param name="section_id"></param>
        /// <param name="timerange"></param>
        /// <param name="type"></param>
        /// <param name="patchid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult DebugStateSummary(int section_id, string timerange, int type, int patchid)
        {
            if (patchid == 0)
            {
                throw new BadRequestException(RequestEnum.UserOrProductIsRequired);
            }
            var times = timerange.Split(" - ");
            var success = DateTime.TryParse(times[0], out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(times[1], out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }
            dtEnd = dtEnd.AddDays(1).AddSeconds(-1);
            dtEnd = dtEnd > DateTime.Now ? DateTime.Now : dtEnd;
            if (dtStart > dtEnd)
            {
                throw new ServerException(100158);
            }

            var machinIds = _machineRepository.GetNCLevelSectionMachineIds(section_id, ProjectId);
            if (!machinIds.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var responses = new List<DebugStateSummary>();
            var states = _currentStateRepository.GetList(q => machinIds.Contains(q.machine_id) && q.machine_state == 2
                                                              && q.project_id == ProjectId && q.status == (int) RowState.Valid).ToList();
            if (!states.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (type == 1) //产品
            {
                var productStates = states.Where(q => q.product_id == patchid);
                if (!productStates.Any())
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }

                var userIds = productStates.Select(m => m.user_mid).Distinct();
                var users = _projectUserRepository.GetList(q => userIds.Contains(q.mid) && q.status == (int) RowState.Valid && q.projectid == ProjectId);
                foreach (var userId in userIds)
                {
                    var user = users.FirstOrDefault(q => q.mid == userId);
                    if (user == null)
                    {
                        continue;
                    }
                    var userStats = productStates.Where(q => q.user_mid == userId);
                    if (!userStats.Any())
                    {
                        continue;
                    }
                    var response = new DebugStateSummary
                    {
                        name = user.name,
                    };

                    foreach (var stat in userStats)
                    {
                        var end = stat.end_time == DateTime.MinValue ? DateTime.Now : stat.end_time;
                        response.datas.Add(Math.Round(end.Subtract(stat.start_time).TotalMinutes, 1));
                    }

                    responses.Add(response);
                }
            }
            else if (type == 2) //用户
            {
                var userStates = states.Where(q => q.user_mid == patchid);
                if (!userStates.Any())
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                var productIds = userStates.Select(m => m.product_id).Distinct();
                var products = _productRepository.GetList(q => productIds.Contains(q.id) && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                foreach (var productId in productIds)
                {
                    var product = products.FirstOrDefault(q => q.id == productId);
                    if (product == null)
                    {
                        continue;
                    }
                    var productStats = userStates.Where(q => q.product_id == productId);
                    if (!productStats.Any())
                    {
                        continue;
                    }

                    var response = new DebugStateSummary
                    {
                        name = product.name,
                    };
                    foreach (var stat in productStats)
                    {
                        var end = stat.end_time == DateTime.MinValue ? DateTime.Now : stat.end_time;
                        response.datas.Add(Math.Round(end.Subtract(stat.start_time).TotalMinutes, 1));
                    }
                    responses.Add(response);
                }
            }

            return new ObjectResult(responses);
        }
    }
}