using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.ModuleEnum;

namespace Siger.Middlelayer.Repository.Repositories
{
    internal class SigerProjectProductReport : ApiConfigRepositoryBase<siger_project_product_report>, ISigerProjectProductReport
    {
        private readonly ApiConfigDbContext _context;
        public SigerProjectProductReport(ApiConfigDbContext context) : base(context)
        {
            _context = context;
        }

       

        /// <summary>
        /// 获取产品的最后一道工序
        /// </summary>
        /// <param name="productDrawCode"></param>
        /// <param name="levelId"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public int GetLastSectionRoute(string productDrawCode, int levelId, int projectId)
        {
            var query = from d in _context.siger_project_product_route
                        join p in _context.siger_project_product on d.productId equals p.id
                        where d.projectId == projectId && p.drawingcode == productDrawCode && d.levelId == levelId
                                                       && d.status == (int)RowState.Valid
                        select d;
            if (query.Any())
            {
                return query.OrderByDescending(q => q.serialNumber).First().sectionId;
            }

            return 0;
        }

        public IEnumerable<int> GetSectionIdsInRoute(string productDrawCode, int levelId, int projectId)
        {
            var query = from d in _context.siger_project_product_route
                        join p in _context.siger_project_product on d.productId equals p.id
                        where d.projectId == projectId && p.drawingcode == productDrawCode && d.levelId == levelId
                              && d.status == (int)RowState.Valid
                        select d;
            if (query.Any())
            {
                return query.Select(m => m.sectionId).ToList();
            }
            return new List<int>();
        }

        public IPagedCollectionResult<ResponseProductReport> ProductReportDataByCode(int pid, string code, string starttime, string endtime, int page, int pagesize)
        {
            var query = from sppr in _context.siger_project_product_report
                        join pro in _context.siger_project_process on sppr.processid equals pro.id
                        where sppr.projectid.Equals(pid) && sppr.status != (int)RowState.Invalid
                        orderby sppr.id
                        select new ResponseProductReport
                        {
                            id = sppr.id,
                            draw_number = sppr.draw_number,
                            end_time = DateTime.Parse(UnixTimeHelper.ConvertIntDateTime(sppr.end_time)),
                            time = DateTime.Parse(UnixTimeHelper.ConvertIntDateTime(sppr.time)),
                            start_time = DateTime.Parse(UnixTimeHelper.ConvertIntDateTime(sppr.start_time)),
                            industrial_waste = sppr.industrial_waste,
                            material_waste = sppr.material_waste,
                            okcount = sppr.actual_output,
                            worker_name = sppr.worker_name,
                            worker_code = sppr.worker_code,
                            uid = sppr.uid,
                            process = pro.Process_name,
                            station = sppr.station,
                            product_name = sppr.product_name,
                            status = sppr.status,
                            output = sppr.output,
                            code = sppr.code,
                            processId = sppr.processid,
                            product_code = sppr.product_code,
                            processType = pro.Process_Type
                        };
            Expression<Func<ResponseProductReport, bool>> funTime = f => true;
            if (DateTime.TryParse(starttime, out var start) && DateTime.TryParse(endtime, out var end))
            {
                funTime = f => f.start_time >= start && f.start_time <= end;
            }
            Expression<Func<ResponseProductReport, bool>> funCode = f => true;
            if (!string.IsNullOrEmpty(code))
            {
                funCode = f => f.code.Equals(code);
            }
            var predicate = funTime.And(funCode);
            var count = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize);
            return new PagedCollectionResult<ResponseProductReport>(entities, count);
        }

        public int InsertProductReportData(siger_project_product_report model)
        {
            _context.siger_project_product_report.Add(model);
            return _context.SaveChanges();
        }
        public int UpdateProductReportData(siger_project_product_report model)
        {
            _context.siger_project_product_report.Update(model);
            return _context.SaveChanges();
        }
        /// <summary>
        /// 获取生产节拍
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="productCode"></param>
        /// <returns></returns>
        public double ProductWorkingHours(int projectId, string productCode)
        {
            var product = _context.siger_project_product.FirstOrDefault(f => f.projectid == projectId && f.code == productCode);
            if (product == null)
                return 0;
            var productRoutes = _context.siger_project_product_route.Where(f => f.projectId == projectId && f.productId == product.id && f.status == (int)RowState.Valid).OrderByDescending(d => d.serialNumber);
            if (!productRoutes.Any())
                return 0;
            var maxRote = productRoutes.FirstOrDefault();
            return maxRote?.working_hours ?? 0;
        }

        public IEnumerable<ResponseEmpReportDetails> GetReportDetails(int uid, int shiftid, long stime, long etime, int projectId)
        {
            var query = from r in _context.siger_project_product_report
                        join l in _context.siger_project_level_section on r.station equals l.id
                        join lp in _context.siger_project_level_section on l.parentid equals lp.id
                        join pd in _context.siger_project_product on r.product_code equals pd.code
                        join u in _context.siger_project_user on r.uid equals u.mid
                        join pr in _context.siger_project_product_route on r.route_id equals pr.id
                        where r.projectid == projectId
                        select new ResponseEmpReportDetails
                        {
                            uid = r.uid,
                            workcode = r.code,
                            product = pd.name,
                            routename = pr.name,
                            workhours = pr.working_hours,
                            foam_hours = pr.foam_hours,
                            reportime = r.time,
                            ok = r.actual_output,
                            ng = r.nok_number,
                            location = $"{lp.title}-{l.title}",
                            machinecode = l.title,
                            shift = r.shift_id
                        };
            Expression<Func<ResponseEmpReportDetails, bool>> funstarttime = f => f.reportime >= stime;
            Expression<Func<ResponseEmpReportDetails, bool>> funendtime = f => f.reportime <= etime;

            Expression<Func<ResponseEmpReportDetails, bool>> funshift = f => true;
            Expression<Func<ResponseEmpReportDetails, bool>> funuser = f => true;
            if (uid != 0)
            {
                funuser = f => f.uid == uid;
            }
            if (shiftid != 0)
            {
                funshift = f => f.shift == shiftid;
            }
            var predicate = funstarttime.And(funendtime).And(funshift).And(funuser);
            return query.Where(predicate);
        }
    }
}
