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

namespace Siger.Middlelayer.QmsRepository.Repositories
{
    internal class QmsSensorParameterRepository : QMSRepositoryBase<siger_qms_sensor_parameter>, IQmsSensorParameterRepository
    {
        private readonly ApiQmsDbContext _context;
        public QmsSensorParameterRepository(ApiQmsDbContext context) : base(context)
        {
            _context = context;
        }
        /// <summary>
        /// 导入传感器台账
        /// </summary>
        /// <param name="standards"></param>
        /// <param name="projectid"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        public CommonImportResult ImportInspectDataCountValue(IEnumerable<SensorParameter> standards, int projectid, int userid)
        {
            var errors = new List<string>();
            var rowIndex = 1;
            var sensorModel = _context.siger_qms_sensor_parameter.Where(f => f.projectid.Equals(projectid) && f.status != (int)RowState.Invalid);
            //检查输入信息
            foreach (var p in standards)
            {
                rowIndex++;
                //获取相关实体
                var machineExtend = _context.siger_project_machine_extend.FirstOrDefault(f => f.status == (int)RowState.Valid && f.machine_shortname.Equals(p.machine));//此处建议siger_project_machine_extend加上projectid
                if (machineExtend == null)
                {
                    errors.Add($"{rowIndex},{(int)QMSEnum.MachineNotExist}");
                }
                var sensorTypeModel = _context.siger_qms_sensor_type.FirstOrDefault(f => f.projectid.Equals(projectid) && f.status == (int)RowState.Valid && f.title.Equals(p.type));
                var userModel = _context.siger_project_user.FirstOrDefault(f => f.projectid.Equals(projectid) && f.status == (int)RowState.Valid && f.work_code.Equals(p.mark_user));
                var unitModel = EnumHelper.EnumToList(typeof(CycleUnit)).Select(s => s.Description);
                if (sensorTypeModel == null)
                {
                    errors.Add($"{rowIndex},{(int)QMSEnum.SensorTypeNotExist}");
                }
                if (!unitModel.Contains(p.cycle_unit_value))
                {
                    errors.Add($"{rowIndex},{(int)QMSEnum.CycleUnitNotExist}");
                }
                var sectionModel = _context.siger_project_machine_attribution.Where(f => f.machine.Equals(machineExtend.machine_id));
                if (sectionModel == null)
                {
                    errors.Add($"{rowIndex},{(int)QMSEnum.MachineNoStation}");
                }
                if (!string.IsNullOrEmpty(p.calibration_source))
                {
                    var calibration_source = sensorModel.FirstOrDefault(f => f.sensor_code.Equals(p.calibration_source));
                    if (calibration_source == null)
                    {
                        errors.Add($"{rowIndex},{(int)QMSEnum.SensorNotExist}");
                    }
                }
                if (!string.IsNullOrEmpty(p.sensor1))
                {
                    var sensor1 = sensorModel.FirstOrDefault(f => f.sensor_code.Equals(p.sensor1));
                    if (sensor1 == null)
                    {
                        errors.Add($"{rowIndex},{(int)QMSEnum.SensorNotExist}");
                    }
                }
                if (!string.IsNullOrEmpty(p.sensor2))
                {
                    var sensor2 = sensorModel.FirstOrDefault(f => f.sensor_code.Equals(p.sensor2));
                    if (sensor2 == null)
                    {
                        errors.Add($"{rowIndex},{(int)QMSEnum.SensorNotExist}");
                    }
                }
                if (!string.IsNullOrEmpty(p.sensor3))
                {
                    var sensor3 = sensorModel.FirstOrDefault(f => f.sensor_code.Equals(p.sensor3));
                    if (sensor3 == null)
                    {
                        errors.Add($"{rowIndex},{(int)QMSEnum.SensorNotExist}");
                    }
                }
                if (!string.IsNullOrEmpty(p.sensor4))
                {
                    var sensor4 = sensorModel.FirstOrDefault(f => f.sensor_code.Equals(p.sensor4));
                    if (sensor4 == null)
                    {
                        errors.Add($"{rowIndex},{(int)QMSEnum.SensorNotExist}");
                    }
                }
                if (userModel == null)
                {
                    errors.Add($"{rowIndex},{(int)QMSEnum.MarkUserValid}");
                }
            }
            if (errors.Any())
            {
                return new CommonImportResult(0, string.Join(";", errors));
            }
            var entities = new List<siger_qms_sensor_parameter>();
            var count = 0;//计数器
            var sensor_codes = CreateSensorCode(projectid, standards.Count());
            foreach (var item in standards)
            {
                var machineModel = _context.siger_project_machine_extend.FirstOrDefault(f => f.status == (int)RowState.Valid && f.machine_shortname.Equals(item.machine));//此处建议siger_project_machine_extend加上projectid
                var sensorTypeModel = _context.siger_qms_sensor_type.FirstOrDefault(f => f.projectid.Equals(projectid) && f.status == (int)RowState.Valid && f.title.Equals(item.type));
                var sectionModel = _context.siger_project_machine_attribution.FirstOrDefault(f => f.machine.Equals(machineModel.machine_id));
                var unitModel = EnumHelper.EnumToList(typeof(CycleUnit));
                var userModel = _context.siger_project_user.FirstOrDefault(f => f.projectid.Equals(projectid) && f.status == (int)RowState.Valid && f.work_code.Equals(item.mark_user));
                var marktime = UnixTimeHelper.ConvertDataTimeLong(item.marktime);
                if (machineModel != null && sensorTypeModel != null)
                {
                    var entity = Mapper<SensorParameter, siger_qms_sensor_parameter>.Map(item);
                    if (item.verification.Equals("是"))
                    {
                        entity.verification = 1;
                    }
                    entity.mark_time = (int)marktime;
                    entity.sensor_code = sensor_codes[count];
                    entity.projectid = projectid;
                    entity.mid = machineModel.machine_id;
                    entity.typeid = sensorTypeModel.id;
                    var cycleUnit = unitModel.FirstOrDefault(f => f.Description.Equals(item.cycle_unit_value)).EnumValue;
                    entity.cycle_unit = cycleUnit;
                    entity.station = sectionModel?.station ?? 0;
                    entity.cycletime = CalTimeStamp((CycleUnit)entity.cycle_unit, entity.cycle);
                    entity.mark_uid = userModel.mid;
                    if (entity.mark_time != 0)
                    {
                        entity.nexttime = entity.cycletime + entity.mark_time;
                    }
                    entities.Add(entity);
                }
                count++;
            }
            try
            {
                _context.siger_qms_sensor_parameter.AddRange(entities);
                _context.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// 获取传感器状态
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="type"></param>
        /// <param name="code"></param>
        /// <param name="mid"></param>
        /// <param name="lastdtStart"></param>
        /// <param name="lastdtEnd"></param>
        /// <param name="nextdtStart"></param>
        /// <param name="nextdtEnd"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        public IPagedCollectionResult<siger_qms_sensor_parameter> GetSensorParameterData(int projectId, int type, string code, int mid,
            int lastdtStart, int lastdtEnd, int nextdtStart, int nextdtEnd, int page, int pagesize)
        {
            Expression<Func<siger_qms_sensor_parameter, bool>> funCode = f => true;
            Expression<Func<siger_qms_sensor_parameter, bool>> funType = f => true;
            Expression<Func<siger_qms_sensor_parameter, bool>> funMachine = f => true;
            Expression<Func<siger_qms_sensor_parameter, bool>> funLast = f => true;
            Expression<Func<siger_qms_sensor_parameter, bool>> funNext = f => true;
            if (type != 0)
            {
                var typeids = GetSensorTypeSonLevel(type, projectId).Select(s=>s.id).Distinct();
                funType = f => typeids.Contains(f.typeid);
            }
            if (!string.IsNullOrEmpty(code))
            {
                funCode = f => f.sensor_code.Equals(code);
            }
            if (mid != 0)
            {

                funMachine = f => f.mid.Equals(mid);
            }
            if (lastdtStart != 0 && lastdtEnd != 0)
            {
                funLast = f => f.mark_time >= lastdtStart && f.mark_time <= lastdtEnd;
            }
            if (nextdtEnd != 0 && nextdtStart != 0)
            {
                funNext = f => f.nexttime >= nextdtStart && f.nexttime <= nextdtEnd;
            }
            var query = from i in _context.siger_qms_sensor_parameter
                        where i.projectid.Equals(projectId) && i.status != (int)RowState.Invalid
                        select i;
            var predicates = funCode.And(funType).And(funLast).And(funNext).And(funMachine);
            var total = query.Count(predicates);
            var entities = query.Where(predicates).Skip((page - 1) * pagesize).Take(pagesize);
            return new PagedCollectionResult<siger_qms_sensor_parameter>(entities, total);
        }
        /// <summary>
        /// 传感器详情信息
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="type"></param>
        /// <param name="code"></param>
        /// <param name="mid"></param>
        /// <param name="lastdtStart"></param>
        /// <param name="lastdtEnd"></param>
        /// <param name="nextdtStart"></param>
        /// <param name="nextdtEnd"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <param name="status"></param>
        /// <param name="check"></param>
        /// <param name="appove"></param>
        /// <param name="model"></param>
        /// <param name="id"></param>
        /// <param name="check2"></param>
        /// <returns></returns>
        public IPagedCollectionResult<ResponseSensorDetailData> GetSensorDetailData(int projectId, int type, string code, int mid,
            int lastdtStart, int lastdtEnd, int nextdtStart, int nextdtEnd, int page, int pagesize, int status, int check, int appove,
            string model, int id, int check2)
        {
            Expression<Func<ResponseSensorDetailData, bool>> funCode = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funType = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funMachine = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funLast = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funNext = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funStatus = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funCheck = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funCheck2 = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funAppove = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funModel = f => true;
            Expression<Func<ResponseSensorDetailData, bool>> funId = f => true;
            if (id != 0)
            {
                funId = f => f.id.Equals(id);
            }
            if (type != 0)
            {
                funType = f => f.typeid.Equals(type);
            }
            if (!string.IsNullOrEmpty(code))
            {
                funCode = f => f.sensor_code.Equals(code);
            }
            if (!string.IsNullOrEmpty(model))
            {
                funModel = f => f.model.Equals(model);
            }
            if (mid != 0)
            {
                funMachine = f => f.mid.Equals(mid);
            }
            if (lastdtStart != 0 && lastdtEnd != 0)
            {
                funLast = f => f.mark_time >= lastdtStart && f.mark_time <= lastdtEnd;
            }
            if (nextdtEnd != 0 && nextdtStart != 0)
            {
                funNext = f => f.nexttime >= nextdtStart && f.nexttime <= nextdtEnd;
            }
            if (status != 0)
            {
                funStatus = f => f.status == status;
            }
            if (appove != 0)
            {
                funAppove = f => f.approvaluser == appove;
            }
            if (check != 0)
            {
                funCheck = f => f.checkuser == check;
            }
            if (check2 != 0)
            {
                funCheck2 = f => f.checkuser2 == check2;
            }
            var query = from i in _context.siger_qms_sensor_parameter
                        join d in _context.siger_qms_sensor_detail on i.sensor_code equals d.sensor_code
                        where i.projectid.Equals(projectId) && i.status != (int)RowState.Invalid && d.status != (int)RowState.Invalid
                        orderby i.mid
                        select new ResponseSensorDetailData
                        {
                            typeid = i.typeid,
                            sensor_code = i.sensor_code,
                            name = i.name,
                            mid = i.mid,
                            result = d.result,
                            fid = d.fid,
                            remark = d.remark,
                            mark_time = i.mark_time,
                            status = d.status,
                            nexttime = i.nexttime,
                            markuser = d.uid,
                            approvaluser = d.approvaluser,
                            checkuser = d.checkuser,
                            checkuser2 = d.checkuser2,
                            upload_time = d.upload_time,
                            approve_time = d.approve_time,
                            appearance = d.appearance,
                            label = d.label,
                            supplier = d.supplier,
                            history_fid = d.history_fid,
                            history_result = d.history_result,
                            id = d.id,
                            report_type = d.type,
                        };
            var predicates = funCode.And(funType).And(funLast).And(funNext).And(funMachine).And(funStatus).And(funAppove).And(funCheck).And(funCheck2).And(funModel).And(funId);
            var total = query.Count(predicates);
            var entities = query.Where(predicates).Skip((page - 1) * pagesize).Take(pagesize);
            return new PagedCollectionResult<ResponseSensorDetailData>(entities, total);
        }
        /// <summary>
        /// 计算周期时间
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="cycle"></param>
        /// <returns></returns>
        public int CalTimeStamp(CycleUnit unit, double cycle)
        {
            switch (unit)
            {
                case CycleUnit.Hour:
                    return (int)(3600 * cycle);
                case CycleUnit.Day:
                    return (int)(24 * 3600 * cycle);
                case CycleUnit.Mounth:
                    return (int)(30 * 24 * 3600 * cycle);
                default:
                    return 0;
            }
        }
        /// <summary>
        /// 生成传感器编号
        /// </summary>
        /// <param name="projectid"></param>
        /// <returns></returns>
        public string CreateSensorCode(int projectid)
        {
            var ret = new StringBuilder();
            ret.Append("SHT-TS-");
            var data = _context.siger_qms_sensor_parameter.Where(f => f.projectid.Equals(projectid) && f.status != (int)RowState.Invalid && f.sensor_code.Contains("SHT-TS-")).Max(s => s.sensor_code);
            if (data == null)
            {
                ret.Append("0001");
                return ret.ToStr();
            }
            var next = data.Replace("SHT-TS-", "").ToInt() + 1;
            ret.Append(next.ToStr().PadLeft(4, '0'));
            return ret.ToStr();
        }
        private List<string> CreateSensorCode(int projectid, int count)
        {
            var ret = new List<string>();
            var data = _context.siger_qms_sensor_parameter.Where(f => f.projectid.Equals(projectid) && f.status != (int)RowState.Invalid && f.sensor_code.Contains("SHT-TS-")).Max(s => s.sensor_code);
            var currentNo = 1;
            if (data != null)
            {
                currentNo = data.Replace("SHT-TS-", "").ToInt();
            }
            for (int i = 0; i < count; i++)
            {
                currentNo++;
                var sb = new StringBuilder();
                sb.Append("SHT-TS-");
                sb.Append(currentNo.ToStr().PadLeft(4, '0'));
                ret.Add(sb.ToStr());
            }
            return ret;
        }

        public IEnumerable<siger_qms_sensor_type> GetSensorTypeSonLevel(int parent, int projectid)
        {
            var query = from c in _context.siger_qms_sensor_type
                        where c.parentid == parent && c.projectid == projectid && c.status == (int)RowState.Valid
                        select c;
            return query.ToList().Concat(query.ToList().SelectMany(t => GetSensorTypeSonLevel(t.id, projectid))).ToList();
        }
    }
}
