using DeviceRepair.Models;
using DeviceRepair.Models.Device;
using DeviceRepair.Models.History;
using DeviceRepair.Utils;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;

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

        /// <summary>
        /// 通过设备编号查询设备信息
        /// </summary>
        /// <param name="EquipmentID"></param>
        /// <returns></returns>
        public APIResponseData GetModelByEquipmentID(string EquipmentID)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");
                DeviceInformationInfo Data = CurrentDb.AsQueryable().First(x => x.EquipmentID.Equals(EquipmentID, StringComparison.CurrentCultureIgnoreCase));
                apiResponseData.Code = 1;
                apiResponseData.Data = Data;
                apiResponseData.Message = "";
            }
            catch (SqlSugarException ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="FilterValue"></param>
        /// <returns></returns>
        public APIResponseData GetQuery(string FilterValue)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");

                int aid = 0;
                int.TryParse(FilterValue, out aid);

                var exp = Expressionable.Create<View_DriveInfomationModel>()
                          .OrIF(aid > 0, t1 => t1.AutoID == aid)
                          .OrIF(!string.IsNullOrEmpty(FilterValue),
                            t1 => t1.EquipmentID.Equals(FilterValue, StringComparison.CurrentCultureIgnoreCase)
                            || t1.EquipmentName.Contains(FilterValue)
                            || t1.Remarks.Contains(FilterValue)
                            || t1.Specification.Contains(FilterValue)).ToExpression();//拼接表达式

                var Datas = db.Queryable<DeviceInformationInfo, MaintenanceFormVersionInfo>(
                        (t1, t2) => new object[] { JoinType.Left, t1.MaintenanceFormVersion == t2.AutoID }
                        ).Select((t1, t2) => new View_DriveInfomationModel
                        {
                            AutoID = t1.AutoID,
                            ChangeDate = t1.ChangeDate,
                            ChangeUser = t1.ChangeUser,
                            CreatDate = t1.CreatDate,
                            CreatUser = t1.CreatUser,
                            EquipmentCategory = t1.EquipmentCategory,
                            EquipmentID = t1.EquipmentID,
                            EquipmentName = t1.EquipmentName,
                            EquipmentOriginalvalue = t1.EquipmentOriginalvalue,
                            EquipmentStatus = t1.EquipmentStatus,
                            InstallationLocation = t1.InstallationLocation,
                            MaintenanceFormVersion = t1.MaintenanceFormVersion,
                            MaintenanceFormVersionName = t2.FormName,
                            MaintenanceFormStatus = t2.FormStatus,
                            Manufacturer = t1.Manufacturer,
                            OperatingParameters = t1.OperatingParameters,
                            OwningUnit = t1.OwningUnit,
                            Remarks = t1.Remarks,
                            SerialNumber = t1.SerialNumber,
                            Specification = t1.Specification,
                            Totalcapacity = t1.Totalcapacity,
                            UsingDate = t1.UsingDate,
                            VersionCode = t2.VersionCode,
                            VersionRev = t2.VersionRev,
                            WarrantyPeriod = t1.WarrantyPeriod,
                            Weight = t1.Weight
                        }).Where(exp)
                        .ToList();

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

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="FilterValue"></param>
        /// <returns></returns>
        public APIResponseData GetDataByAutoID(int pk)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                if (pk <= 0)
                    throw new Exception("参数：设备表主键编号不能小于等于0！");

                //创建表达式
                var exp = Expressionable.Create<DeviceInformationInfo>();
                exp.And(x => x.AutoID == pk);
                DeviceInformationInfo Item = db.Queryable<DeviceInformationInfo>().Where(exp.ToExpression())?.First();

                apiResponseData.Message = "";
                apiResponseData.Code = 1;
                apiResponseData.Data = Item;
            }
            catch (SqlSugarException ex)
            {
                db.RollbackTran();//数据回滚
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                db.RollbackTran();//数据回滚
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 修改设备信息
        /// </summary>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public APIResponseData UpdateDriveInformation(Dictionary<string, object> dictionary, HeaderModel Operation)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };

            db.ChangeDatabase("main");

            bool isSuccess = false;
            try
            {
                if (!dictionary.ContainsKey("AutoID"))
                    throw new Exception("未能获取到主键编号");
                int AutoID = Convert.ToInt32(dictionary["AutoID"]);

                DateTime CurrentDate = DateTime.Now;

                if (dictionary.ContainsKey("Route"))
                    dictionary.Remove("Route");

                if (AutoID == 0)
                {
                    if (dictionary.ContainsKey("CreatDate"))
                        dictionary["CreatDate"] = CurrentDate;

                    if (dictionary.ContainsKey("ChangeDate"))
                        dictionary["ChangeDate"] = CurrentDate;

                    if (dictionary.ContainsKey("VersionCode"))
                        dictionary.Remove("VersionCode");

                    if (dictionary.ContainsKey("VersionRev"))
                        dictionary.Remove("VersionRev");

                    long aid = db.Insertable(dictionary).AS("DriveInformation").IgnoreColumns("AutoID").ExecuteReturnBigIdentity();

                    if (aid > 0)
                    {
                        db.CommitTran();

                        apiResponseData.Code = 1;
                        apiResponseData.Message = "";
                        apiResponseData.Data = null;
                    }
                }
                else
                {
                    DeviceInformationInfo model = db.Queryable<DeviceInformationInfo>().Single(x => x.AutoID == AutoID);
                    if (model == null)
                        throw new Exception("未能获取的设备信息");

                    db.BeginTran();
                    isSuccess = db.Updateable(dictionary).AS("DriveInformation").WhereColumns("AutoID").ExecuteCommandHasChange();
                    if (isSuccess)
                    {
                        db.CommitTran();
                        apiResponseData.Code = 1;
                        apiResponseData.Message = "";
                        apiResponseData.Data = null;

                        db.ChangeDatabase("log");
                        DriveInformationHistory log = ObjectExtend.Mapper<DriveInformationHistory, DeviceInformationInfo>(model);
                        log.DriveInformationID = log.AutoID;
                        log.AutoID = 0;
                        log.Changer = Operation.Operator;
                        log.ApplyDate = CurrentDate;
                        long id = db.Insertable(log).ExecuteReturnIdentity();
                    }
                }
            }
            catch (SqlSugarException ex)
            {
                db.RollbackTran();//数据回滚
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                db.RollbackTran();//数据回滚
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 获取树形结构
        /// </summary>
        /// <param name="FilterValue"></param>
        /// <returns></returns>
        public APIResponseData GetDeviceTreeDatas(string FilterValue)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");

                int aid = 0;
                int.TryParse(FilterValue, out aid);

                var exp = Expressionable.Create<DeviceInformationInfoTree>()
                          .OrIF(aid > 0, t1 => t1.AutoID == aid)
                          .OrIF(!string.IsNullOrEmpty(FilterValue),
                            t1 => t1.EquipmentID.Equals(FilterValue, StringComparison.CurrentCultureIgnoreCase)
                            || t1.EquipmentName.Contains(FilterValue)
                            || t1.Remarks.Contains(FilterValue)
                            || t1.Specification.Contains(FilterValue)).ToExpression();//拼接表达式

                var Root = db.Queryable<DeviceRouteInfo>().Where(x => x.Status).OrderBy(x => x.AutoID).ToList().ToDictionary(x => x.AutoID, x => x);

                List<DeviceInformationInfoTree> Menus = new List<DeviceInformationInfoTree>();
                foreach (KeyValuePair<int, DeviceRouteInfo> item in Root)
                {
                    DeviceRouteInfo dev = item.Value;
                    Menus.Add(new DeviceInformationInfoTree
                    {
                        EquipmentName = dev.Name,
                        RouteAutoId = dev.GUID,
                        ParentRouteId = dev.ParentID != 0 ? Root[dev.ParentID].GUID : Guid.Empty
                    });
                }

                int[] RouteIds = Root.Keys.ToArray();
                var Datas = db.Queryable<DeviceInformationInfo, MaintenanceFormVersionInfo, DeviceRouteInfo>(
                        (t1, t2, t3) => new object[] {
                            JoinType.Left, t1.MaintenanceFormVersion == t2.AutoID,
                            JoinType.Left, t1.Route == t3.AutoID
                        }
                        ).Select((t1, t2, t3) => new DeviceInformationInfoTree
                        {
                            AutoID = t1.AutoID,
                            ChangeDate = t1.ChangeDate,
                            ChangeUser = t1.ChangeUser,
                            CreatDate = t1.CreatDate,
                            CreatUser = t1.CreatUser,
                            EquipmentCategory = t1.EquipmentCategory,
                            EquipmentID = t1.EquipmentID,
                            EquipmentName = t1.EquipmentName,
                            EquipmentOriginalvalue = t1.EquipmentOriginalvalue,
                            EquipmentStatus = t1.EquipmentStatus,
                            InstallationLocation = t1.InstallationLocation,
                            MaintenanceFormVersion = t1.MaintenanceFormVersion,
                            MaintenanceFormVersionName = t2.FormName,
                            Manufacturer = t1.Manufacturer,
                            OperatingParameters = t1.OperatingParameters,
                            OwningUnit = t1.OwningUnit,
                            Remarks = t1.Remarks,
                            SerialNumber = t1.SerialNumber,
                            Specification = t1.Specification,
                            Totalcapacity = t1.Totalcapacity,
                            UsingDate = t1.UsingDate,
                            VersionCode = t2.VersionCode,
                            VersionRev = t2.VersionRev,
                            WarrantyPeriod = t1.WarrantyPeriod,
                            Weight = t1.Weight,
                            Route = t3.AutoID,
                            RouteAutoId = t1.GUID,
                            //ParentRouteId =  SqlFunc.ContainsArray(RouteIds, t1.Route) ? Root[t1.Route].Guid : Guid.Empty
                        }).Where(exp)
                        .ToList();

                foreach (DeviceInformationInfoTree item in Datas)
                {
                    item.ParentRouteId = RouteIds.Contains(item.Route) ? Root[item.Route].GUID : Guid.Empty;
                }



                List<Guid> HasValues = new List<Guid>();
                Guid[] gids = Datas.Select(x => x.ParentRouteId).Distinct().ToArray(); ;

                do
                {
                    if (HasValues.Count == 0)
                        HasValues.AddRange(gids);

                    gids = Menus.Where(x => gids.Contains(x.RouteAutoId)).Select(s => s.ParentRouteId).Distinct().ToArray();
                    HasValues.AddRange(gids);
                } while (gids.All(x => x == Guid.Empty));

                Menus.RemoveAll(x => !HasValues.Contains(x.RouteAutoId));


                Menus.AddRange(Datas);

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

        public decimal GetSum(List<DeviceInformationInfoTree> t1, List<DeviceRouteInfo> t2, int RouteID)
        {
            decimal value = 0;
            DeviceRouteInfo r = t2.FirstOrDefault(x => x.AutoID == RouteID);
            if (r != null)
            {

            }
            return value;
        }
    }
}
