using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Request;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Common.Helpers;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using Siger.Middlelayer.Repository.Response;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.CncRepository.Response;
using NPOI.SS.Formula.Functions;

namespace Siger.ApiCNC.Controllers
{
    public class ProduceWorkingController : BaseController
    {
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerProjectMachineClock _sigerProjectMachineClock;
        private readonly ISigerProjectUserRepository _userRepository;
        private readonly ISigerProjectClockRecord _clockRecord;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly IWorkingGroupRepository _workingGroup;
        private readonly ISigerProjectShiftRepository _sigerProjectShift;
        private readonly ISigerUserRepository _sigerUserRepository;
        private readonly ISigerProjectClockRecordtotal _projectClockRecordtotal;
        private readonly ISigerProjectProductReport _sigerProjectProduct;
        private readonly IUnitOfWork _unitOfWork;

        public ProduceWorkingController(ISigerProjectMachineRepository machineRepository,ISigerProjectMachineClock sigerProjectMachineClock, ISigerProjectUserRepository userRepository, ISigerProjectClockRecord clockRecord, ISigerProjectMachineAttributionRepository machineAttributionRepository,
           IWorkingGroupRepository workingGroup,ISigerProjectShiftRepository sigerProjectShift,ISigerUserRepository sigerUserRepository,ISigerProjectClockRecordtotal projectClockRecordtotal ,ISigerProjectProductReport sigerProjectProduct,IUnitOfWork unitOfWork)
        {
            _machineRepository = machineRepository;
            _sigerProjectMachineClock = sigerProjectMachineClock;
            _userRepository = userRepository;
            _clockRecord = clockRecord;
            _machineAttributionRepository = machineAttributionRepository;
            _workingGroup = workingGroup;
            _sigerProjectShift = sigerProjectShift;
            _sigerUserRepository = sigerUserRepository;
            _projectClockRecordtotal = projectClockRecordtotal;
            _sigerProjectProduct = sigerProjectProduct;
            _unitOfWork = unitOfWork;
        }

        /// <summary>
        /// app生产执行报工(确认签到)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult ClockWorking(string ids)
        {
            var idList = ids.Split(',');

            var user = _sigerUserRepository.Get(f => f.id == UserId);
            if (user.type==2)
            {
                throw new BadRequestException(CommonEnum.NoDepartPermission);
            }
            var wprkGroup = _workingGroup.Get(f => f.midSplit.Contains(UserId));
            var _frequency = string.Empty;
            var _shitid = 0;
            if (wprkGroup != null)
            {
                var dic = _sigerProjectShift.GetCurrentShit(wprkGroup.shiftSplit, UserId);
                if (dic.Any())
                {
                    _shitid = dic.FirstOrDefault().Key;
                    _frequency = dic.FirstOrDefault().Value;
                }
            }
            foreach (var id in idList)
            {
                //
                var machineAttr = _machineAttributionRepository.Get(f => f.machine == id.ToInt() && f.status == (int)RowState.Valid);
                var recordExist = _clockRecord.Get(f => f.machine_id == id.ToInt() && f.uid == UserId && f.projectid == ProjectId && f.status == (int)RowState.Valid&&f.endtime==null);
                if(recordExist != null)
                {
                    throw new BadRequestException(CncEnum.MachineIsSignIn);
                }
                var colck = new siger_project_clock_record
                {
                    station= machineAttr.station,
                    machine_id = id.ToInt(),
                    uid = UserId,
                    starttime = DateTime.Now,
                    projectid = ProjectId,
                    state = 1,
                    shiftid=_shitid,
                    shift = _frequency
                };
                _clockRecord.Insert(colck);
                if (_unitOfWork.Commit() <= 0)
                {
                    continue;
                }
                //第一次上机
                var clockMachineObj = _sigerProjectMachineClock.Get(f => f.machine == id.ToInt());
                if (clockMachineObj == null)
                {
                    _sigerProjectMachineClock.Insert(new siger_project_machine_clock
                    {
                        machine = id.ToInt(),
                        project_id = ProjectId,
                        status = (int)RowState.Valid,
                        user = UserId,
                        record = colck.id
                    });
                }
                else
                {
                    var record = _clockRecord.Get(f => f.id == clockMachineObj.record);
                    var totalSecond = Math.Round((DateTime.Now - record.starttime).TotalSeconds, 4);
                    if (record != null)
                    {
                        record.endtime = DateTime.Now;
                        record.state = 0;
                        record.workinghour = totalSecond;
                        _clockRecord.Update(record);
                        //calculate total
                        SetRecordTotal(record,totalSecond);
                    }
                   
                    //记录新上机人员
                    clockMachineObj.user = UserId;
                    clockMachineObj.record = colck.id;

                    _sigerProjectMachineClock.Update(clockMachineObj);
                }


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

        /// <summary>
        /// web生产执行报工(确认签到)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult ClockWorkings(int section)
        {
            var user = _sigerUserRepository.Get(f => f.id == UserId);
            if (user.type == 2)
            {
                throw new BadRequestException(CommonEnum.NoDepartPermission);
            }
            var wprkGroup = _workingGroup.Get(f => f.midSplit.Contains(UserId));
            var _frequency = string.Empty;
            var _shitid = 0;
            if (wprkGroup != null)
            {
                var dic = _sigerProjectShift.GetCurrentShit(wprkGroup.shiftSplit, UserId);
                if (dic.Any())
                {
                    _shitid = dic.FirstOrDefault().Key;
                    _frequency = dic.FirstOrDefault().Value;
                }
            }
            var machineAttr = _machineAttributionRepository.Get(f => f.station == section && f.status == (int)RowState.Valid);
            if (machineAttr == null)
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }
            var recordExist = _clockRecord.Get(f => f.station == section && f.uid == UserId && f.projectid == ProjectId && f.status == (int)RowState.Valid && f.endtime == null);
            if (recordExist != null)
            {
                throw new BadRequestException(CncEnum.MachineIsSignIn);
            }
            var colck = new siger_project_clock_record
            {
                station = section,
                machine_id = machineAttr.machine,
                uid = UserId,
                starttime = DateTime.Now,
                projectid = ProjectId,
                state = 1,
                shiftid = _shitid,
                shift = _frequency
            };
            _clockRecord.Insert(colck);
            if (_unitOfWork.Commit() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            //第一次上机
            var clockMachineObj = _sigerProjectMachineClock.Get(f => f.machine == machineAttr.machine);
            if (clockMachineObj == null)
            {
                _sigerProjectMachineClock.Insert(new siger_project_machine_clock
                {
                    machine = machineAttr.machine,
                    project_id = ProjectId,
                    status = (int)RowState.Valid,
                    user = UserId,
                    record = colck.id
                });
            }
            else
            {
                var record = _clockRecord.Get(f => f.id == clockMachineObj.record);
                var totalSecond = Math.Round((DateTime.Now - record.starttime).TotalSeconds, 4);
                if (record != null)
                {
                    record.endtime = DateTime.Now;
                    record.state = 1;
                    record.workinghour = totalSecond;
                    _clockRecord.Update(record);
                    //SetRecordTotal(record, totalSecond);
                }

                //记录新上机人员
                clockMachineObj.user = UserId;
                clockMachineObj.record = colck.id;

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


        /// <summary>
        ///绩效统计
        /// </summary>
        /// <param name="record"></param>
        /// <param name="totalSecond"></param>
        void SetRecordTotal(siger_project_clock_record record, double totalSecond)
        {

            var stime = UnixTimeHelper.ConvertDataTimeLong(record.starttime);
            var etime = UnixTimeHelper.ConvertDataTimeLong(record.endtime);
            var rptDts = _sigerProjectProduct.GetReportDetails(record.uid, record.shiftid, stime, etime, ProjectId);

            var clockDts = _clockRecord.GetClockDetails(record.starttime, record.endtime, record.shiftid, record.uid, ProjectId);
            var machineCnt = clockDts.GroupBy(f => f.machine).Count();
            var dayCnt = (record.endtime-record.starttime).TotalDays;

            //生产工时todo
            var productHour = rptDts.Sum(f => f.ok * f.workhours);

            //签到设备
            var machineSign =dayCnt>0? machineCnt / dayCnt:0d;

            //作业效率
            var efficiency = totalSecond>0?productHour /totalSecond:0d;

            var recordtotal = _projectClockRecordtotal.Get(f => f.projectid == ProjectId && f.busidate == record.starttime.Date && f.uid == record.uid && f.shiftid == record.shiftid);
            if (recordtotal == null)
            {
                //var projectUser = _userRepository.GetCurrentUserInfo(record.uid);
                _projectClockRecordtotal.Insert(new siger_project_clock_record_ttl
                {
                    projectid = ProjectId,
                    busidate = record.starttime.Date,
                    machine_id = record.machine_id,
                    uid = record.uid,
                    shiftid = record.shiftid,
                    shift = record.shift,
                    workinghour = totalSecond,
                    producehour = productHour,
                    machinesign = machineSign,
                    efficiency = efficiency,
                    status = (int)RowState.Valid
                });
            }
            else
            {
                recordtotal.workinghour += totalSecond;
                recordtotal.producehour += productHour;
                recordtotal.machinesign += machineSign;
                recordtotal.efficiency += efficiency;

                _projectClockRecordtotal.Update(recordtotal);
            }

        }
      
        /// <summary>
        /// 生产执行报工(确认签到页面展示)
        /// </summary>
        /// <param name="machineCode"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetData(string machineCode)
        {
          
            var data = _machineRepository.GetMachineuser(machineCode, ProjectId).FirstOrDefault();
            if (data == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var machineRecord = _sigerProjectMachineClock.Get(f => f.machine == data.id);
            if (machineRecord == null)
            {
                data.username = "暂无人员负责";
            }
            else
            {
                var usersr = _userRepository.Get(q => q.mid == machineRecord.user && q.projectid == ProjectId);
                data.username = usersr == null ? "暂无人员负责" : usersr.name;

            }
            return new ObjectResult(data);
        }

        /// <summary>
        /// 生产执行报工(下班签退)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult EndWorking()
        {

            var machineRecords = _sigerProjectMachineClock.GetList(f => f.user == UserId).ToList();
            if (!machineRecords.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            foreach(var rec in machineRecords)
            {
                rec.user = 0;
             
                _sigerProjectMachineClock.Update(rec);

                var recordObj = _clockRecord.Get(f => f.id == rec.record);
                var totalSecond = Math.Round((DateTime.Now - recordObj.starttime).TotalSeconds, 4);
                recordObj.endtime = DateTime.Now;
                recordObj.state = 0;
                recordObj.workinghour = totalSecond;
                _clockRecord.Update(recordObj);

                SetRecordTotal(recordObj, totalSecond);

            }

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

        /// <summary>
        /// web生产执行报工(下班签退)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult EndWorkings(int section)
        {
            var machineAttr = _machineAttributionRepository.Get(f => f.station == section && f.status == (int)RowState.Valid);
            if (machineAttr==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var machineRecords = _sigerProjectMachineClock.Get(f => f.user == UserId && f.machine== machineAttr.machine);
            if (machineRecords==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var recordObj = _clockRecord.Get(f => f.id == machineRecords.record);
            var totalSecond = Math.Round((DateTime.Now - recordObj.starttime).TotalSeconds, 4);
            recordObj.endtime = DateTime.Now;
            recordObj.state = 0;
            recordObj.workinghour = totalSecond;
            _clockRecord.Update(recordObj);
            machineRecords.user = 0;
            _sigerProjectMachineClock.Update(machineRecords);
           // SetRecordTotal(recordObj, totalSecond);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }


        /// <summary>
        /// 生产报工下班签退(页面展示)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [NoTokenValidateFilter]
        public IActionResult GetOutData()
        {

            var machineRecords = _sigerProjectMachineClock.GetList(f => f.project_id == ProjectId && f.user == UserId);
            if (!machineRecords.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
          
            var recordIds = machineRecords.Select(s => s.record).ToList();
            var data = _sigerProjectMachineClock.GetClockInData(recordIds, ProjectId);
       
            return new ObjectResult(data);
        }

        /// <summary>
        /// 打卡记录表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetData([FromBody] RequestDateClockRecord request)
        {
            // var entityTotal = _clockRecord.GetAchieveMentTotal(request.starttime.ToDateTime(), request.endtime.ToDateTime(), request.section, request.shift, request.users, ProjectId, request.page, request.pagesize);
            var entityTotal = _clockRecord.GetPagedRecord(request.stationline, request.starttime, request.endtime, request.section,
                request.shift, request.users, request.page, request.pagesize, ProjectId);
            return new PagedObjectResult(entityTotal.Data, entityTotal.Total);

        }

        /// <summary>
        /// 员工绩效统计
        /// </summary>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <param name="section"></param>
        /// <param name="shift"></param>
        /// <param name="user_id"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAchievementList(string starttime, string endtime, int section, int shift, int user_id, int page, int pagesize,int toexcel)
        {
            if (toexcel != 0)
            {
               pagesize = 999999999;
            }
            var sdatetime = starttime.ToDateTime();
            var edatetime = endtime.ToDateTime();
            if (sdatetime==DateTime.MinValue)
            {
                sdatetime = DateTime.Now.Date;
            }
            if(edatetime == DateTime.MinValue)
            {
                edatetime = DateTime.Now.Date.AddHours(24);
            }
          

            var clockResult = _clockRecord.GetAchieveMentTotal(sdatetime, edatetime, section, shift, user_id, ProjectId, page, pagesize);
            var clockDts = _clockRecord.GetClockDetails(sdatetime, edatetime, shift,user_id,ProjectId);
            var machineTtl = clockDts.GroupBy(g => g.machine).Count();
            var result = clockResult.Data.ToList();
            var day = (edatetime - sdatetime).TotalDays;
            foreach(var clock in result)
            {
                clock.avemachine = day > 0 ? Math.Round( machineTtl / day,2) : 0d;
            }

            if (toexcel == 0)
            {
                return new PagedObjectResult(result, clockResult.Total);
            }
            var machines = _machineRepository.GetProjectLanguage(ProjectId);
            return Exportjx(result, machines);
        }

        /// <summary>
        /// 绩效统计查看详情之打卡记录
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="shiftid"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDetail(int userId,int shiftid,long stime,long etime)
        {
  
            var sdtime = UnixTimeHelper.ConvertStringDateTime(stime.ToString());
            var edtime = UnixTimeHelper.ConvertStringDateTime(etime.ToString());

            var rptDts = _clockRecord.GetClockDetails(sdtime,edtime,shiftid,userId,ProjectId);
            return new ObjectResult(rptDts);
        }

        /// <summary>
        /// 绩效统计查看详情之报工记录
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="shiftid"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetRecordDetail (int userId, int shiftid, long stime, long etime)
        {
            var rptDts = _sigerProjectProduct.GetReportDetails(userId, shiftid, stime, etime, ProjectId);
            return new ObjectResult(rptDts);
        }

        /// <summary>
        /// 查询班次
        /// </summary>
        /// <param name="sectionId"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetFrequency(int sectionId)
        {
            var data = _sigerProjectShift.GetList(s => s.sectionid == sectionId && s.projectid == ProjectId && s.status == (int)RowState.Valid).ToList();

            return new ObjectResult(data);
        }



        /// <summary>
        /// 判断当前工位状态
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult WorkingType(int section)
        {
            var record = new RequestClockRecord();
            var recordObj = _clockRecord.GetList(f => f.station == section ).OrderByDescending(q=>q.id).FirstOrDefault();
            if (recordObj!=null)
            {
                if (recordObj.state==1)
                {
                    var usersr = _userRepository.Get(q => q.mid == recordObj.uid && q.projectid == ProjectId);
                    if (recordObj.uid == UserId)
                    {
                        record.type = (int)Personnel.Own;
                        record.name = usersr != null ? usersr.name : "";
                        record.time = recordObj.starttime;
                    }
                    else
                    {
                        record.type = (int)Personnel.TheOthers;
                        record.name = usersr != null ? usersr.name : "";
                        record.time = recordObj.starttime;
                    }
                }
                else
                {
                    record.type = (int)Personnel.NoOne;
                }
            }
            else
            {
                record.type = (int)Personnel.NoOne;
            }
            return new ObjectResult(record);
        }
    }
}
