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

namespace Siger.Middlelayer.DncRepository.Repositories
{
    internal class SigerProjectDncUserPowerRepository : DncRepositoryBase<siger_project_dnc_user_power>,
        ISigerProjectDncUserPowerRepository
    {
        private readonly ApiDncDbContext context;

        public SigerProjectDncUserPowerRepository(ApiDncDbContext context) : base(context)
        {
            this.context = context;
        }

        public ResponseCheckButtons GetCheckbuttons(int userId)
        {
            return GetCheckPower(userId);
        }


        public IEnumerable GetCheckUsers(int projectId)
        {
            var poweruser =
                context.siger_project_dnc_user_power.Where(f =>
                    f.projectid == projectId && f.status == (int) RowState.Valid);
            var result = from usr in context.siger_user
                join poweruserData in poweruser on usr.id equals poweruserData.mid into tmp1
                from t1 in tmp1.DefaultIfEmpty()
                join projectuser in context.siger_project_user on usr.id equals projectuser.mid into re
                from r in re.DefaultIfEmpty()
                where usr.status == (int) RowState.Valid &&
                      r.status == (int) RowState.Valid &&
                      (t1.check_power == 1 || t1.all_power == 1 || usr.type == (int) UserType.Admin) &&
                      r.projectid == projectId
                select new
                {
                    mid = usr.id,
                    r.name,
                    r.work_code
                };
            return result.AsEnumerable();
        }

        public IEnumerable GetProducts(int projectId)
        {
            var data = context.siger_project_product.Where(f => f.projectid == projectId && f.status == 1)
                .AsEnumerable();

            return data;
        }

        public IEnumerable GetsectionLists(int projectId)
        {
            var data = context.siger_project_section.Where(f => f.projectid == projectId && f.status == 1)
                .AsEnumerable();

            return data;
        }

        public IEnumerable GetUsers(int projectId, int? sectionid)
        {
            //获取已设置权限的人员
            var users = context.siger_project_dnc_user_power
                .Where(f => f.projectid == projectId && f.status == (int) RowState.Valid).Select(f => f.mid);

            var data = from a in context.siger_project_user
                join b in context.siger_project_section on a.sectionid equals b.id into result
                from r in result.DefaultIfEmpty()
                where (sectionid == null || sectionid == 0 || r.id == sectionid) && a.projectid == projectId &&
                      a.status == (int) RowState.Valid && r.status == (int) RowState.Valid
                      && !users.Contains(a.mid)
                //如果存在已设置的人员,需要过滤not in，否则返回所有数据
                select new
                {
                    a.mid,
                    a.name,
                    a.work_code
                };
            return data.AsEnumerable();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="userId">登录人员id</param>
        /// <param name="mid"></param>
        /// <param name="add_power"></param>
        /// <param name="del_power"></param>
        /// <param name="check_power"></param>
        /// <param name="all_power"></param>
        /// <param name="remark"></param>
        /// <returns></returns>
        public bool AddPower(int projectId, int userId, int mid, int add_power, int del_power, int check_power,
            int all_power, string remark)
        {
            if (!CheckPower(userId))
            {
                return false;
            }

            context.siger_project_dnc_user_power.Add(
                new siger_project_dnc_user_power
                {
                    mid = mid,
                    add_power = add_power,
                    del_power = del_power,
                    check_power = check_power,
                    all_power = all_power,
                    remark = remark,
                    projectid = projectId,
                    createmid = userId,
                    createtime = UnixTimeHelper.GetNow(),
                    status = (int) RowState.Valid
                }
            );
            return context.SaveChanges() > 0;
        }

        /// <summary>
        /// 修改权限
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="powerid"></param>
        /// <param name="add_power"></param>
        /// <param name="del_power"></param>
        /// <param name="check_power"></param>
        /// <param name="all_power"></param>
        /// <param name="remark"></param>
        /// <param name="projectId"></param>
        public bool EditPower(int userId, int powerid, int add_power, int del_power, int check_power, int all_power,
            string remark, int projectId)
        {
            if (!CheckPower(userId))
            {
                return false;
            }

            var data = context.siger_project_dnc_user_power.FirstOrDefault(q =>
                q.id == powerid && q.projectid == projectId);
            if (data != null)
            {
                data.add_power = add_power;
                data.del_power = del_power;
                data.check_power = check_power;
                data.all_power = all_power;
                data.remark = remark;
                context.siger_project_dnc_user_power.Update(data);
                return context.SaveChanges() > 0;
            }

            return false;
        }

        /// <summary>
        /// 删除用户权限
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="powerid"></param>
        public bool DelPower(int userId, int powerid)
        {
            if (!CheckPower(userId))
            {
                return false;
            }

            var data = context.siger_project_dnc_user_power.Find(powerid);
            if (data != null)
            {
                data.status = (int) RowState.Invalid;
                context.siger_project_dnc_user_power.Update(data);
                return context.SaveChanges() > 0;
            }

            return false;
        }

        /// <summary>
        /// 获取指定用户的权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private ResponseCheckButtons GetCheckPower(int userId)
        {
            //判断是否为管理员,管理员返回所有权限
            if (context.siger_user.Any(f => f.id == userId && f.type == (int) UserType.Admin))
            {
                return new ResponseCheckButtons
                {
                    addpower = (int) PowerStatu.ON,
                    delpower = (int) PowerStatu.ON,
                    checkpower = (int) PowerStatu.ON,
                    allpower = (int) PowerStatu.ON
                };
            }

            var result =
                context.siger_project_dnc_user_power.FirstOrDefault(f =>
                    f.mid == userId && f.status == (int) RowState.Valid);
            if (result == null)
            {
                return new ResponseCheckButtons
                {
                    addpower = (int) PowerStatu.OFF,
                    delpower = (int) PowerStatu.OFF,
                    checkpower = (int) PowerStatu.OFF,
                    allpower = (int) PowerStatu.OFF
                };
            }

            return new ResponseCheckButtons
            {
                addpower = result.add_power == (int) PowerStatu.ON ? (int) PowerStatu.ON : (int) PowerStatu.OFF,
                delpower = result.del_power == (int) PowerStatu.ON ? (int) PowerStatu.ON : (int) PowerStatu.OFF,
                checkpower = result.check_power == (int) PowerStatu.ON ? (int) PowerStatu.ON : (int) PowerStatu.OFF,
                allpower = result.all_power == (int) PowerStatu.ON ? (int) PowerStatu.ON : (int) PowerStatu.OFF
            };
        }

        /// <summary>
        /// 权限设置列表
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="sectionID"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <param name="totalCount"></param>
        public IEnumerable GetPowerLists(int projectId, int? sectionID, int page, int pagesize, out int totalCount)
        {
            var users = context.siger_project_user.AsQueryable();
            var data = from a in context.siger_project_dnc_user_power
                join b in users on a.mid equals b.mid into tmp1
                from t1 in tmp1.DefaultIfEmpty()
                join c in users on a.createmid equals c.mid into tmp2
                from t2 in tmp2.DefaultIfEmpty()
                join d in context.siger_project_section on t1.sectionid equals d.id into re
                from r in re.DefaultIfEmpty()
                where a.projectid == projectId && a.status == (int) RowState.Valid &&
                      t1.status == (int) RowState.Valid &&
                      r.status == (int) RowState.Valid
                orderby a.createtime descending
                select new ResponsePowerInfo
                {
                    id = a.id,
                    mid = a.mid,
                    add_power = a.add_power,
                    del_power = a.del_power,
                    check_power = a.check_power,
                    all_power = a.all_power,
                    status = a.status,
                    createtime = a.createtime,
                    createmid = a.createmid,
                    remark = a.remark,
                    projectid = a.projectid,
                    powername = t1.name,
                    work_code = t1.work_code,
                    create_name = t2.name,
                    sectiontitle = r.title,
                    sectionid = r.id,
                };
            Expression<Func<ResponsePowerInfo, bool>> nameExpression = q => true;
            if (sectionID != null && sectionID != 0)
            {
                nameExpression = q => q.sectionid == sectionID;
            }

            var qq = data.ToList();
            var pre = nameExpression;
            totalCount = data.Count(pre);

            var result = data.Where(pre).Skip((page - 1) * pagesize).Take(pagesize).ToList();

            foreach (var item in result)
            {
                item.add_power_str = (item.add_power == 1)
                    ? EnumHelper.GetEnumDesc(PowerStatu.ON)
                    : EnumHelper.GetEnumDesc(PowerStatu.OFF);
                item.del_power_str = (item.del_power == 1)
                    ? EnumHelper.GetEnumDesc(PowerStatu.ON)
                    : EnumHelper.GetEnumDesc(PowerStatu.OFF);
                item.check_power_str = (item.check_power == 1)
                    ? EnumHelper.GetEnumDesc(PowerStatu.ON)
                    : EnumHelper.GetEnumDesc(PowerStatu.OFF);
                item.all_power_str = (item.all_power == 1)
                    ? EnumHelper.GetEnumDesc(PowerStatu.ON)
                    : EnumHelper.GetEnumDesc(PowerStatu.OFF);
                item.create_time = (item.createtime == 0) ? "NA" : UnixTimeHelper.ConvertIntDateTime(item.createtime);
            }

            return result;
        }

        public bool HasApprovalPower(int userId)
        {
            //判断操作的用户是否有管理员权限或所有权限
            var power = GetCheckPower(userId);
            //只给普通用户添加权限
            if (power.allpower == (int) PowerStatu.ON)
            {
                return true;
            }

            if (power.checkpower == (int) PowerStatu.ON)
            {
                return true;
            }

            return false;
        }

        public bool HasEditPower(int userId)
        {
            //判断操作的用户是否有管理员权限或所有权限
            var power = GetCheckPower(userId);
            //只给普通用户添加权限
            if (power.allpower == (int) PowerStatu.ON)
            {
                return true;
            }

            if (power.addpower == (int) PowerStatu.ON)
            {
                return true;
            }

            return false;
        }

        public bool HasDeletePower(int userId)
        {
            //判断操作的用户是否有管理员权限或所有权限
            var power = GetCheckPower(userId);
            //只给普通用户添加权限
            if (power.allpower == (int) PowerStatu.ON)
            {
                return true;
            }

            if (power.delpower == (int) PowerStatu.ON)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断用户是否具有管理员权限或全部操作权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public bool CheckPower(int userId)
        {
            //判断操作的用户是否有管理员权限或所有权限
            var power = GetCheckPower(userId);
            //只给普通用户添加权限
            if (power.allpower != (int) PowerStatu.ON)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 用户是普通用户，没有管理权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private bool CheckHasPower(int userId)
        {
            //判断操作的用户是否有管理员权限或所有权限
            var power = GetCheckPower(userId);
            //既不是管理员也没其他权限
            if (power == null)
            {
                return false;
            }

            if (power.allpower != (int) PowerStatu.ON)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 查询人员权限信息
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="powerid"></param>
        /// <returns></returns>
        public ResponseUserPowerInfo GetPowerUserInfo(int projectId, int powerid)
        {
            var data = (from a in context.siger_project_dnc_user_power
                join b in context.siger_project_user on a.mid equals b.mid into tmp1
                from t1 in tmp1.DefaultIfEmpty()
                join c in context.siger_project_section on t1.sectionid equals c.id into result
                from r in result.DefaultIfEmpty()
                where a.id == powerid && a.projectid == projectId && a.status == (int) RowState.Valid &&
                      t1.status == (int) RowState.Valid && r.status == (int) RowState.Valid
                select new ResponseUserPowerInfo
                {
                    id = a.id,
                    mid = a.mid,
                    add_power = a.add_power,
                    del_power = a.del_power,
                    check_power = a.check_power,
                    all_power = a.all_power,
                    status = a.status,
                    createtime = a.createtime,
                    createmid = a.createmid,
                    remark = a.remark,
                    projectid = a.projectid,
                    title = r.title,
                    name = t1.name
                }).FirstOrDefault();
            return data;
        }

        public IEnumerable<ResponseProgramList> GetProgramLists(int projectID, int userID, string programcode,
            string product_name, int checkstatus, int page,
            int pagesize, out int totalCount)
        {
            //程序号
            IQueryable<siger_project_dnc_program> programs;
            if (!string.IsNullOrWhiteSpace(programcode))
            {
                programs = context.siger_project_dnc_program.Where(f =>
                    f.program_code.Contains(programcode) && f.status == (int) RowState.Valid);
            }
            else
            {
                programs = context.siger_project_dnc_program;
            }

            IQueryable<siger_project_product> products;
            //产品名称
            if (!string.IsNullOrWhiteSpace(product_name))
            {
                products = context.siger_project_product.Where(f =>
                    f.name.Contains(product_name) && f.status == (int) RowState.Valid
                                                  && f.projectid == projectID);
            }
            else
            {
                products = context.siger_project_product;
            }

            //审核状态
            if (checkstatus != 0)
            {
                programs = programs.Where(f => f.checkstatus == checkstatus);
            }

            //普通用户
            if (!CheckHasPower(userID))
            {
                //可以查看自己创建的程序和自己审核的程序
                programs = programs.Where(f => (f.createmid == userID || f.checkmid == userID));
            }
            var data = from program in programs
                       join product in products on program.productid equals product.id
                       join uc in context.siger_project_user on program.createmid equals uc.mid into tmp2
                       from t2 in tmp2.DefaultIfEmpty()
                       join uk in context.siger_project_user on program.checkmid equals uk.mid into re
                       from r in re.DefaultIfEmpty()
                       where program.projectid == projectID && program.status == (int)RowState.Valid
                       orderby program.checkstatus, program.createtime
                       select new ResponseProgramList
                       {
                           id = program.id,
                           program_code = program.program_code,
                           productid = program.productid,
                           createmid = program.createmid,
                           create_time = program.createtime,
                           createtime = program.createtime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(program.createtime),
                           create_remark = program.create_remark ?? "NA",
                           checkmid = program.checkmid,
                           checktime = program.checktime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(program.checktime),
                           check_remark = program.check_remark ?? "NA",
                           checkinfo = program.checkinfo,
                           checkstatus = program.checkstatus,
                           status = program.status,
                           file_url = program.file_url,
                           file_name = program.file_name,
                           projectid = program.projectid,
                           file_size = program.file_size,
                           productname = product.name,
                           code = product.drawingcode,
                           createname = t2 == null ? "" : t2.name,
                           checkname = r == null ? "" : r.name,
                           drawno = program.drawno,
                           workproccess = program.work_proccess
                       };
            totalCount = data.Count();
            var result = data.OrderByDescending(q => q.create_time).Skip((page - 1) * pagesize).Take(pagesize)
                .AsNoTracking().ToList();
            if (!result.Any())
            {
                return new List<ResponseProgramList>();
            }

            return result;
        }

        public void AddProgramPost(int projectID, int userID, string file_url, string file_name, string file_size,
            string programcode, int productid, int checkmid, string createremark)
        {
            //CheckPower(userID);
            context.siger_project_dnc_program.Add(new siger_project_dnc_program
            {
                checkstatus = (int) CheckState.Waiting,
                program_code = programcode,
                productid = productid,
                checkmid = checkmid,
                create_remark = createremark,
                createmid = userID,
                projectid = projectID,
                createtime = UnixTimeHelper.GetNow(),
                file_url = file_url,
                file_name = file_name,
                file_size = file_size,
                status = (int) RowState.Valid
            });
            context.SaveChanges();
        }

        public IPagedCollectionResult<ResponseProgramList> GetProgramLists(int projectId, int userId, string createmid,
            string checkmid, string product, int page, int pagesize, int starttime, int endtime)
        {
            //程序号
            var programs = context.siger_project_dnc_program.Where(f => f.checkstatus == (int) CheckState.Checked)
                .AsQueryable();
            var ucs = context.siger_project_user.AsQueryable();
            if (!string.IsNullOrEmpty(createmid))
            {
                ucs = ucs.Where(f => f.name.Contains(createmid));
            }

            var uks = context.siger_project_user.AsQueryable();
            if (!string.IsNullOrEmpty(checkmid))
            {
                uks = uks.Where(f => f.name.Contains(checkmid));
            }

            var products = context.siger_project_product.AsQueryable();
            //产品名称
            if (!string.IsNullOrEmpty(product))
            {
                products = products.Where(f => f.drawingcode.Contains(product) || f.name.Contains(product));
            }

            if (starttime != 0 && endtime != 0)
            {
                programs = programs.Where(f => f.createtime > starttime && f.createtime < endtime ||
                                               f.checktime > starttime && f.checktime < endtime);
            }

            var data = from program in programs
                join productData in products on program.productid equals productData.id into tmp1
                from t1 in tmp1.DefaultIfEmpty()
                join uc in ucs on program.createmid equals uc.mid into tmp2
                from t2 in tmp2.DefaultIfEmpty()
                join uk in uks on program.checkmid equals uk.mid into re
                from r in re.DefaultIfEmpty()
                where program.projectid == projectId && program.status == (int) RowState.Valid &&
                      t1.status == (int) RowState.Valid &&
                      t2.status == (int) RowState.Valid && r.status == (int) RowState.Valid
                orderby program.checkstatus, program.createtime
                select new ResponseProgramList
                {
                    id = program.id,
                    program_code = program.program_code,
                    productid = program.productid,
                    createmid = program.createmid,
                    createtime =
                        program.createtime
                            .ToString(), //??"NA",//==0? "NA":UnixTimeHelper.ConvertIntDateTime(program.createtime),
                    create_remark = program.create_remark ?? "NA",
                    checkmid = program.checkmid,
                    checktime = program.checktime
                        .ToString(), // ==null|| program.checktime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(program.checktime),
                    check_remark = program.check_remark ?? "NA",
                    checkinfo = program.checkinfo,
                    checkstatus = program.checkstatus,
                    status = program.status,
                    file_url = program.file_url,
                    file_name = program.file_name,
                    projectid = program.projectid,
                    file_size = program.file_size,
                    productname = t1.name,
                    code = t1.drawingcode,
                    createname = t2.name,
                    checkname = r.name,
                    drawno = program.drawno,
                    workproccess = program.work_proccess
                };

            //普通用户
            if (!CheckHasPower(userId))
            {
                //可以查看自己创建的程序和自己审核的程序
                programs = programs.Where(f => f.createmid == userId || f.checkmid == userId);
            }

            var totalCount = data.Count();
            var result = data.Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();

            return new PagedCollectionResult<ResponseProgramList>(result, totalCount);
        }

        public IPagedCollectionResult<ResponseProgramsList> GetMainProgramLists(int projectId, int userId,string productId, string processCode, string programCode, int checkStatus, int page, int pagesize)
        {
            Expression<Func<ResponseProgramsList, bool>> productidException = q => true;
            Expression<Func<ResponseProgramsList, bool>> processnameException = q => true;
            Expression<Func<ResponseProgramsList, bool>> checkstatusException = q => true;
            Expression<Func<ResponseProgramsList, bool>> programcodeException = q => true;

            var query = from s in context.siger_project_dnc_program
                        join t in context.siger_project_user on s.createmid equals t.mid into temp
                        from tp in temp.DefaultIfEmpty()
                        join p in context.siger_project_user on s.checkmid equals p.mid into temps
                        from ts in temps.DefaultIfEmpty()
                        join r in context.siger_project_product on s.productid equals r.id
                        join d in context.siger_project_product_route on s.process_code.ToInt() equals d.id
                        where s.projectid == projectId && s.status == (int)RowState.Valid && s.program_type == (int)progromType.Main
                        orderby s.createtime descending, s.checkstatus ascending
                        select new ResponseProgramsList
                        {
                            id = s.id,
                            program_code = s.program_code,
                            productid = s.productid,
                            createmid = s.createmid,
                            create_time = s.createtime,
                            createtime = s.createtime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.createtime),
                            create_remark = s.create_remark ?? "NA",
                            checkmid = s.checkmid,
                            checktime = s.checktime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.checktime),
                            check_remark = s.check_remark ?? "NA",
                            checkinfo = s.checkinfo,
                            checkstatus = s.checkstatus,
                            status = s.status,
                            file_url = s.file_url,
                            file_name = s.file_name,
                            projectid = s.projectid,
                            file_size = s.file_size,
                            productname = r.name,
                            code = r.drawingcode,
                            createname = tp == null ? "" : tp.name,
                            checkname = ts == null ? "" : ts.name,
                            drawno = s.drawno,
                            workproccess = s.work_proccess,
                            program_version = s.program_version,
                            program_number = s.program_number,
                            process_name = d.name,
                        };
            if (!string.IsNullOrEmpty(productId))
            {
                productidException = q => q.productid == productId.ToInt();
            }
            if(!string.IsNullOrEmpty(processCode))
            {
                processnameException = q => q.process_code == processCode;
            }
            if(!string.IsNullOrEmpty(programCode))
            {
                programcodeException = q => q.program_code.Contains(programCode);
            }
            if(checkStatus!=0)
            {
                checkstatusException = q => q.checkstatus == checkStatus;
            }

            if (!CheckHasPower(userId))
            {
                query = query.Where(s => s.checkmid == userId || s.createmid == userId);
            }

            var predicate = productidException.And(processnameException).And(programcodeException).And(checkstatusException);

            var totalCount = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<ResponseProgramsList>(entities, totalCount);
        }

        public IPagedCollectionResult<ResponseVersionRecord> GetProgramVersionInfo(string programCode, int userId, int projectId, int page, int pagesize)
        {
            var query = from s in context.siger_project_dnc_program
                        join t in context.siger_project_user on s.createmid equals t.mid into temp
                        from tp in temp.DefaultIfEmpty()
                        join p in context.siger_project_user on s.checkmid equals p.mid into temps
                        from ts in temps.DefaultIfEmpty()
                        where s.program_code == programCode && s.projectid == projectId && s.program_type == (int)progromType.Main
                        select new ResponseVersionRecord
                        {
                            id = s.id,
                            checker = ts == null ? "" : ts.name,
                            creater = tp == null ? "" : tp.name,
                            create_time = s.createtime,
                            file_name = s.file_name,
                            program_version = s.program_version,
                            checkmid = s.checkmid,
                            createmid = s.createmid
                        };
            if (!CheckHasPower(userId))
            {
                query = query.Where(s => s.checkmid == userId || s.createmid == userId);
            }

            var totalCount = query.Count();
            var entities = query.Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();

            return new PagedCollectionResult<ResponseVersionRecord>(entities, totalCount);
        }

        public IPagedCollectionResult<ResponseProgramsList> GetMainProgramListChecked(int projectId, int userId, string keywords, string createBy, string checkBy, int startDate, int endDate, int page, int pagesize)
        {
            Expression<Func<ResponseProgramsList, bool>> keywordsException = q => true;
            Expression<Func<ResponseProgramsList, bool>> createByException = q => true;
            Expression<Func<ResponseProgramsList, bool>> checkByException = q => true;
            Expression<Func<ResponseProgramsList, bool>> startException = q => true;
            Expression<Func<ResponseProgramsList, bool>> endException = q => true;

            var query = from s in context.siger_project_dnc_program
                        join t in context.siger_project_user on s.createmid equals t.mid into temp
                        from tp in temp.DefaultIfEmpty()
                        join p in context.siger_project_user on s.checkmid equals p.mid into temps
                        from ts in temps.DefaultIfEmpty()
                        join r in context.siger_project_product on s.productid equals r.id
                        join d in context.siger_project_product_route on s.process_code.ToInt() equals d.id
                        where s.projectid == projectId && s.status == (int)RowState.Valid && s.program_type == (int)progromType.Main&&s.checkstatus==(int)CheckState.Checked
                        orderby s.createtime descending
                        select new ResponseProgramsList
                        {
                            id = s.id,
                            program_code = s.program_code,
                            productid = s.productid,
                            createmid = s.createmid,
                            create_time = s.createtime,
                            createtime = s.createtime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.createtime),
                            create_remark = s.create_remark ?? "NA",
                            checkmid = s.checkmid,
                            checktime = s.checktime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.checktime),
                            check_remark = s.check_remark ?? "NA",
                            checkinfo = s.checkinfo,
                            checkstatus = s.checkstatus,
                            status = s.status,
                            file_url = s.file_url,
                            file_name = s.file_name,
                            projectid = s.projectid,
                            file_size = s.file_size,
                            productname = r.name,
                            code = r.drawingcode,
                            createname = tp == null ? "" : tp.name,
                            checkname = ts == null ? "" : ts.name,
                            drawno = s.drawno,
                            workproccess = s.work_proccess,
                            program_version = s.program_version,
                            program_number = s.program_number,
                            process_name = d.name,
                        };
            if (!string.IsNullOrEmpty(keywords))
            {
                keywordsException = q => q.productname.Contains(keywords) || q.program_code.Contains(keywords) || q.productid == keywords.ToInt();
            }
            if (!string.IsNullOrEmpty(createBy))
            {
                createByException = q => q.createname.Contains(createBy);
            }
            if (!string.IsNullOrEmpty(checkBy))
            {
                checkByException = q => q.checkname.Contains(checkBy);
            }
            if (startDate != 0)
            {
                startException = q => UnixTimeHelper.GetUnixByShortDate(q.createtime) > startDate;
            }
            if(endDate!=0)
            {
                endException = q => UnixTimeHelper.GetUnixByShortDate(q.createtime) < endDate;
            }

            if (!CheckHasPower(userId))
            {
                query = query.Where(s => s.checkmid == userId || s.createmid == userId);
            }
            var predicate = keywordsException.And(createByException).And(checkByException).And(startException).And(endException);

            var totalCount = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<ResponseProgramsList>(entities, totalCount);
        }

        public IPagedCollectionResult<ResponseProgramsList> GetMainProgramList(int projectId, int userId, string keywords, string createBy, string checkBy, int startDate, int endDate, int product_id, int route_id, int page, int pagesize)
        {
            Expression<Func<ResponseProgramsList, bool>> keywordsException = q => true;
            Expression<Func<ResponseProgramsList, bool>> createByException = q => true;
            Expression<Func<ResponseProgramsList, bool>> checkByException = q => true;
            Expression<Func<ResponseProgramsList, bool>> startException = q => true;
            Expression<Func<ResponseProgramsList, bool>> endException = q => true;
            Expression<Func<ResponseProgramsList, bool>> productIdException = q => true;
            Expression<Func<ResponseProgramsList, bool>> routeIdException = q => true;

            var query = from s in context.siger_project_dnc_program
                        join t in context.siger_project_user on s.createmid equals t.mid into temp
                        from tp in temp.DefaultIfEmpty()
                        join p in context.siger_project_user on s.checkmid equals p.mid into temps
                        from ts in temps.DefaultIfEmpty()
                        join r in context.siger_project_product on s.productid equals r.id
                        join d in context.siger_project_product_route on s.process_code.ToInt() equals d.id
                        where s.projectid == projectId && s.status == (int)RowState.Valid && s.program_type == (int)progromType.Main && s.checkstatus == (int)CheckState.Checked
                        orderby s.createtime descending
                        select new ResponseProgramsList
                        {
                            id = s.id,
                            program_code = s.program_code,
                            productid = s.productid,
                            createmid = s.createmid,
                            create_time = s.createtime,
                            createtime = s.createtime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.createtime),
                            create_remark = s.create_remark ?? "NA",
                            checkmid = s.checkmid,
                            checktime = s.checktime == 0 ? "NA" : UnixTimeHelper.ConvertIntDateTime(s.checktime),
                            check_remark = s.check_remark ?? "NA",
                            checkinfo = s.checkinfo,
                            checkstatus = s.checkstatus,
                            status = s.status,
                            file_url = s.file_url,
                            file_name = s.file_name,
                            projectid = s.projectid,
                            file_size = s.file_size,
                            productname = r.name,
                            code = r.drawingcode,
                            createname = tp == null ? "" : tp.name,
                            checkname = ts == null ? "" : ts.name,
                            drawno = s.drawno,
                            workproccess = s.work_proccess,
                            program_version = s.program_version,
                            program_number = s.program_number,
                            process_name = d.name,
                            process_id=d.id
                        };
            if (!string.IsNullOrEmpty(keywords))
            {
                keywordsException = q => q.productname.Contains(keywords) || q.program_code.Contains(keywords) || q.productid == keywords.ToInt();
            }
            if (!string.IsNullOrEmpty(createBy))
            {
                createByException = q => q.createname.Contains(createBy);
            }
            if (!string.IsNullOrEmpty(checkBy))
            {
                checkByException = q => q.checkname.Contains(checkBy);
            }
            if (startDate != 0)
            {
                startException = q => UnixTimeHelper.GetUnixByShortDate(q.createtime) > startDate;
            }
            if (endDate != 0)
            {
                endException = q => UnixTimeHelper.GetUnixByShortDate(q.createtime) < endDate;
            }
            if (product_id > 0)
            {
                productIdException = q => q.productid== product_id;
            }
            if (route_id > 0)
            {
                routeIdException = q => q.process_id== route_id;
            }
            if (!CheckHasPower(userId))
            {
                query = query.Where(s => s.checkmid == userId || s.createmid == userId);
            }
            var predicate = keywordsException.And(createByException).And(checkByException).And(startException).And(endException).And(productIdException).And(routeIdException);

            var totalCount = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<ResponseProgramsList>(entities, totalCount);
        }
    }
}
