using DeviceRepair.Models;
using DeviceRepair.Models.History;
using DeviceRepair.Models.Logs;
using DeviceRepair.Utils;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;

namespace DeviceRepair.DataAccess
{
    public class PreserveAccess : DbContext<MaintenanceRecordInfo>
    {
        private static PreserveAccess manager;
        public static PreserveAccess Instance
        {
            get
            {
                if (manager == null)
                    manager = new PreserveAccess();
                return manager;
            }
        }

        /// <summary>
        /// 获取保养计划及对应的点检表信息
        /// </summary>
        /// <param name="PrimaryKey"></param>
        public APIResponseData GetPlanAndFormInfo(int PrimaryKey)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = $"获取数据失败！" };
            if (PrimaryKey == 0)
                return new APIResponseData { Code = -1, Message = $"参数【主键编号】不能为空！" };
            try
            {
                db.ChangeDatabase("main");
                var datas = db.Queryable<DriveMaintencePlanInfo, DeviceInformationInfo, MaintenanceFormVersionInfo>((maintencePlan, device, form) =>
                new object[] {
                    JoinType.Left,maintencePlan.EquipmentID == device.AutoID,
                    JoinType.Left,device.MaintenanceFormVersion == form.AutoID
                }).Where((maintencePlan, device, form) => maintencePlan.AutoID == PrimaryKey).Select((maintencePlan, device, form) => new { maintencePlan, form }).First();

                if (datas == null)
                    return new APIResponseData { Code = -1, Message = $"获取数据失败,数据库不存在【主键编号】为【{PrimaryKey}】的数据！" };
                else
                    return new APIResponseData { Code = 1, Data = datas };
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 获取设备保养信息记录
        /// </summary>
        /// <param name="PrimaryKey"></param>
        /// <returns></returns>
        public APIResponseData GetPreserveRecordItemByPrimaryKey(int PrimaryKey)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");
                MaintenanceRecordInfo entity = base.GetSingle(PrimaryKey);
                if (entity == null)
                    return apiResponseData;

                return new APIResponseData { Code = 1, Data = entity };
            }
            catch (SqlSugarException e)
            {
                return new APIResponseData { Code = -1, Message = e.Message };
            }
            catch (Exception e)
            {
                return new APIResponseData { Code = -1, Message = e.Message };
            }
        }

        /// <summary>
        /// 获取点检表表单信息
        /// </summary>
        /// <param name="PrimaryKey"></param>
        /// <returns></returns>
        public MaintenanceFormVersionInfo GetMaintenanceFormVersionSingle(int PrimaryKey)
        {
            MaintenanceFormVersionInfo entity = null;
            try
            {
                db.ChangeDatabase("main");
                entity = db.Queryable<MaintenanceFormVersionInfo>().First(x => x.AutoID == PrimaryKey);
            }
            catch (SqlSugarException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw e;
            }
            return entity;
        }

        /// <summary>
        /// 获取上传的附件
        /// </summary>
        /// <param name="PrimaryKey"></param>
        /// <returns></returns>
        public AttachmentInfo GetAttachmentInfo(int PrimaryKey)
        {
            try
            {
                db.ChangeDatabase("main");
                return db.Queryable<AttachmentInfo>().First(x => x.AutoID == PrimaryKey && x.Status);
            }
            catch (SqlSugarException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// 通过设备主键编号及点检表主键编号获取单条保养信息记录
        /// </summary>
        /// <param name="EquipmentPrimaryID"></param>
        /// <param name="FormPrimaryID"></param>
        /// <returns></returns>
        public APIResponseData GetSingleByEquipmentPrimaryIDAndFormPrimaryID(int EquipmentPrimaryID, int FormPrimaryID)
        {
            if (EquipmentPrimaryID <= 0)
                return new APIResponseData { Code = -1, Message = $"参数【设备表主键编号】不能为空！" };

            if (FormPrimaryID <= 0)
                return new APIResponseData { Code = -1, Message = $"参数【保养点检表主键编号】不能为空！" };

            try
            {
                db.ChangeDatabase("main");
                int year = DateTime.Today.Year;
                MaintenanceRecordInfo entity = CurrentDb.AsQueryable()
                    .OrderBy(x => x.AutoID, OrderByType.Desc)
                    .Take(1).First(x => x.EquipmentPrimaryID == EquipmentPrimaryID && x.FormPrimaryID == FormPrimaryID
                    && x.MYear == year);

                if (entity == null)
                    return new APIResponseData { Code = 1, Data = null };
                else
                    return new APIResponseData { Code = 1, Data = entity };
            }
            catch (SqlSugarException e)
            {
                return new APIResponseData { Code = -1, Message = e.Message };
            }
            catch (Exception ex)
            {
                return new APIResponseData { Code = -1, Message = ex.Message };
            }

        }

        /// <summary>
        /// 获取所有的保养记录数据
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public APIResponseData GetPreserveDatas(string filter)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "获取数据失败" };
            List<View_MaintenanceRecordList> lst = null;
            try
            {
                db.ChangeDatabase("main");
                lst = db.Queryable<MaintenanceRecordInfo, UserInfoModel, DeviceInformationInfo, MaintenanceFormVersionInfo>((t1, t2, t3, t4) => new object[] {
                        JoinType.Inner,t1.CreateBy == t2.AutoID,
                        JoinType.Inner,t1.EquipmentPrimaryID == t3.AutoID,
                        JoinType.Inner,t1.FormPrimaryID == t4.AutoID
                    }).Select((t1, t2, t3, t4) => new View_MaintenanceRecordList
                    {
                        AutoID = t1.AutoID,
                        EquipmentID = t3.AutoID,
                        EquipmentNo = t3.EquipmentID,
                        EquipmenName = t3.EquipmentName,
                        FormVersionID = t4.AutoID,
                        FormVersionName = t4.FormName,
                        FormVersionCode = t4.VersionCode,
                        FormVersionRev = t4.VersionRev,
                        PlanPrimaryID = t1.PlanPrimaryID,
                        PlanType = t1.PlanType,
                        CreateDate = t1.CreateDate,
                        CreateUser = t1.CreateBy,
                        CreateUserName = t2.RealName
                    })?.ToList();

                if (!string.IsNullOrWhiteSpace(filter))
                {
                    filter = filter.ToLower();
                    lst = lst.Where(x =>
                        x.EquipmentID.ToString().Contains(filter)
                         || x.EquipmentNo.ToLower().Contains(filter)
                         || x.EquipmenName.ToLower().Contains(filter)
                         || x.FormVersionName.ToLower().Contains(filter)
                         || x.FormVersionCode.ToLower().Contains(filter)
                         || x.FormVersionRev.ToLower().Contains(filter)
                         || x.CreateUserName.ToLower().Contains(filter)
                    ).ToList();
                }

                apiResponseData.Code = 1;
                apiResponseData.Data = lst;
                apiResponseData.Message = "";
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 获取保养数据
        /// </summary>
        /// <param name="PrimaryKey"></param>
        /// <returns></returns>
        public APIResponseData GetPreserveDetailByID(int PrimaryKey)
        {
            if (PrimaryKey == 0)
                return new APIResponseData { Code = -1, Message = "未能获取到查询条件:保养记录主键ID,或ID等于0。" };

            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = $"获取数据失败！" };
            try
            {
                db.ChangeDatabase("main");
                MaintenanceRecordSubmit model = new MaintenanceRecordSubmit();
                MaintenanceRecordInfo query = db.Queryable<MaintenanceRecordInfo>().Single(x => x.AutoID == PrimaryKey);
                List<AttachmentInfo> att = db.Queryable<AttachmentInfo>().Where(x => x.TableName == "MaintenanceRecord"
                  && x.PrimaryKey == "AutoID" && x.PrimaryValue == (query.AutoID + "") && x.Status).ToList();

                model.Record = query;

                if (att.Count > 0)
                {
                    List<AttachmentInfo> fs = att.Where(x => x.Module == "Attachment").ToList();
                    foreach (AttachmentInfo item in fs)
                    {
                        model.Files.Add(new AttachmentSubmitModel
                        {
                            Datas = File.ReadAllBytes(item.FilePath),
                            Extension = item.Extension,
                            FileName = item.FileName,
                            Module = item.Module
                        });
                    }

                    List<AttachmentInfo> im = att.Where(x => x.Module == "Image").ToList();
                    foreach (AttachmentInfo item in im)
                    {
                        model.Imgs.Add(new AttachmentSubmitModel
                        {
                            Datas = File.ReadAllBytes(item.FilePath),
                            Extension = item.Extension,
                            FileName = item.FileName,
                            Module = item.Module
                        });
                    }
                }

                byte[] byteArray;
                BinaryFormatter formatter = new BinaryFormatter();
                using (MemoryStream stream = new MemoryStream())
                {
                    formatter.Serialize(stream, model);
                    byteArray = stream.ToArray();
                }

                //数据压缩
                byteArray = byteArray.Compress();

                return new APIResponseData { Code = 1, Data = byteArray };
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public APIResponseData Insertable(MaintenanceRecordSubmit entity, HeaderModel Operation)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = $"获取数据失败！" };

            if (entity == null)
                return new APIResponseData { Code = -1, Message = "数据获取失败，传入的数据为空！" };

            try
            {
                db.ChangeDatabase("main");

                db.BeginTran();

                string OperationType = "新增";
                DateTime CurrentDate = DateTime.Now;
                int Identity = 0;

                if (entity.Record.AutoID == 0)
                {
                    entity.Record.ModifyDate = CurrentDate;
                    entity.Record.ModifyBy = Operation.Operator;
                    entity.Record.CreateDate = CurrentDate;
                    Identity = db.Insertable(entity.Record).ExecuteReturnIdentity();
                }
                else
                {
                    OperationType = "修改";

                    MaintenanceRecordHisInfo his = new MaintenanceRecordHisInfo
                    {

                        HisID = entity.Record.AutoID,
                        OperationBy = Operation.Operator,
                        OperationDate = CurrentDate,
                        EquipmentPrimaryID = entity.Record.EquipmentPrimaryID,
                        EquipmentID = entity.Record.EquipmentID,
                        EquipmentName = entity.Record.EquipmentName,
                        Specification = entity.Record.Specification,
                        PlanPrimaryID = entity.Record.PlanPrimaryID,
                        PlanType = entity.Record.PlanType,
                        FormPrimaryID = entity.Record.FormPrimaryID,
                        FormVersionCode = entity.Record.FormVersionCode,
                        FormVersionRev = entity.Record.FormVersionRev,
                        FormName = entity.Record.FormName,
                        MYear = entity.Record.MYear,
                        ContentData = entity.Record.ContentData,
                        CreateBy = entity.Record.CreateBy,
                        CreateDate = entity.Record.CreateDate,
                        ModifyBy = entity.Record.ModifyBy,
                        ModifyDate = entity.Record.ModifyDate,
                        Description = entity.Record.Description
                    };
                    int count = db.Insertable(his).ExecuteCommand();
                    if (count > 0)
                    {
                        entity.Record.ModifyDate = CurrentDate;
                        entity.Record.ModifyBy = Operation.Operator;

                        count = db.Updateable(entity.Record)
                            .UpdateColumns(x => new { x.ContentData, x.ModifyDate, x.ModifyBy })
                            .ExecuteCommand();

                        if (count > 0)
                        {
                            Identity = entity.Record.AutoID;
                        }
                        else
                        {
                            db.RollbackTran();
                            return new APIResponseData { Code = -1, Message = "操作失败！" };
                        }
                    }
                    else
                    {
                        db.RollbackTran();
                        return new APIResponseData { Code = -1, Message = "操作失败！" };
                    }
                }

                if (Identity > 0)
                {
                    //附件存放路径
                    string AttachmentDirectory = Path.Combine(Utils.Config.Configurations.Properties.AttachmentDirectory, DateTime.Today.ToString("yyyyMMdd"));
                    if (!Directory.Exists(AttachmentDirectory))
                        Directory.CreateDirectory(AttachmentDirectory);

                    List<AttachmentInfo> Attas = new List<AttachmentInfo>();

                    #region 附件写入

                    //附件写入
                    foreach (var item in entity.Files)
                    {
                        if (item.AutoID != 0)
                        {
                            int cCount = db.Updateable<AttachmentInfo>().UpdateColumns(x => new { x.Status })
                         .SetColumns(x => x.Status == false)
                         .Where(x => x.AutoID == item.AutoID).ExecuteCommand();
                        }

                        AttachmentInfo atta = new AttachmentInfo
                        {
                            CreateBy = Operation.Operator,
                            FileName = item.FileName,
                            Extension = item.Extension,
                            Module = "Attachment",
                            TableName = "MaintenanceRecord",
                            PrimaryValue = Identity + "",
                            PrimaryKey = "AutoID",
                            ValueType = "int",
                            FilePath = Path.Combine(AttachmentDirectory, $"{Guid.NewGuid()}{item.Extension}"),
                            CreateOn = CurrentDate,
                            Status = true
                        };
                        Attas.Add(atta);
                        File.WriteAllBytes(atta.FilePath, item.Datas);
                    }
                    #endregion

                    #region 图片写入
                    int[] NoneImg = entity.Imgs.Select(x => x.AutoID).Distinct().ToArray();
                    string PrimaryValue = entity.Record.AutoID.ToString();


                    var exp = Expressionable.Create<AttachmentInfo>()
                    .AndIF(NoneImg.Length > 0, x => !SqlFunc.ContainsArray(NoneImg, x.AutoID))
                    .And(x => x.Module == "Image")
                    .And(x => x.TableName == "MaintenanceRecord")
                    .And(x => x.PrimaryKey == "AutoID")
                    .And(x => x.PrimaryValue == PrimaryValue).ToExpression();

                    db.Updateable<AttachmentInfo>().UpdateColumns(x => new { x.Status })
                        .SetColumns(x => x.Status == false)
                        .Where(exp).ExecuteCommand();

                    //if (NoneImg.Length > 0)
                    //{
                    //    int aCount = db.Updateable<AttachmentInfo>().UpdateColumns(x => new { x.Status })
                    //    .SetColumns(x => x.Status == false)
                    //    .Where(x => !SqlFunc.ContainsArray(NoneImg, x.AutoID) && x.Module == "Image" && x.TableName == "MaintenanceRecord" && x.PrimaryKey == "AutoID" && x.PrimaryValue == PrimaryValue).ExecuteCommand();
                    //}
                    //else
                    //{
                    //    int aCount = db.Updateable<AttachmentInfo>().UpdateColumns(x => new { x.Status })
                    //    .SetColumns(x => x.Status == false)
                    //    .Where(x => x.Module == "Image" && x.TableName == "MaintenanceRecord" && x.PrimaryKey == "AutoID" && x.PrimaryValue == PrimaryValue).ExecuteCommand();
                    //}

                    List<int> ImgIds = new List<int>();
                    foreach (var item in entity.Imgs)
                    {
                        if (item.Datas == null && item.AutoID != 0)
                        {
                            ImgIds.Add(item.AutoID);
                            continue;
                        }

                        string FileName = $"{Guid.NewGuid()}.Jpeg";
                        AttachmentInfo atta = new AttachmentInfo
                        {
                            CreateBy = Operation.Operator,
                            FileName = FileName,
                            Extension = ".Jpeg",
                            Module = "Image",
                            TableName = "MaintenanceRecord",
                            PrimaryValue = Identity + "",
                            PrimaryKey = "AutoID",
                            ValueType = "int",
                            FilePath = Path.Combine(AttachmentDirectory, $"{Guid.NewGuid()}.Jpeg"),
                            CreateOn = CurrentDate,
                            Status = true
                        };
                        Attas.Add(atta);
                        File.WriteAllBytes(atta.FilePath, item.Datas);
                    }
                    #endregion

                    //附件插入
                    if (Attas.Count > 0)
                    {
                        bool result = db.Insertable(Attas).ExecuteCommand() > 0;
                        if (!result)
                        {
                            db.RollbackTran();
                            return new APIResponseData { Code = -1, Message = "附件写入失败！" };
                        }
                    }
                    db.CommitTran();

                    apiResponseData.Code = 1;
                    apiResponseData.Message = "";

                    MaintenanceRecordInfo model = db.Queryable<MaintenanceRecordInfo>().First(x => x.AutoID == Identity);

                    db.ChangeDatabase("log");
                    DeviceMaintenanceLogInfo log = new DeviceMaintenanceLogInfo
                    {
                        EquipmentAutoID = model.EquipmentPrimaryID,
                        EquipmentID = model.EquipmentID,
                        EquipmentName = model.EquipmentName,
                        PlanID = model.PlanPrimaryID,
                        PlanType = model.PlanType,
                        OperationComputer = Operation.ClientName,
                        OperationUserName = Operation.OperatorName,
                        OperationDate = CurrentDate,
                        OperationIP = Operation.IPAddress,
                        OperationType = OperationType,
                        OperationUser = Operation.Operator
                    };
                    db.Insertable(log).ExecuteCommand();

                    return apiResponseData;
                }

                db.RollbackTran();
                return new APIResponseData { Code = -1 };
            }
            catch (SqlSugarException e)
            {
                db.RollbackTran();
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                db.RollbackTran();
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }
    }
}
