using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Mapster;
using Nirvana.Common;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Waste.Domain;

namespace Waste.Application.Device
{
    /// <summary>
    /// 设备管理
    /// </summary>
    public class DeviceService : BaseInfoService, IDeviceService, ITransient
    {
        private readonly ISqlSugarRepository<W_Device> repository;
        private readonly SqlSugarClient dbClient;
        private readonly IBusinessService _businessService;

        public DeviceService(ISqlSugarRepository<W_Device> sqlSugarRepository, IBusinessService businessService)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            _businessService = businessService;
        }

        /// <summary>
        /// 设备批量操作
        /// </summary>
        /// <param name="deviceBatchModel"></param>
        /// <returns></returns>
        public async Task<ResultInfo> BatchSetAsync(DeviceBatchModel deviceBatchModel)
        {
            var emptyid = Guid.Empty;
            //设备所属商户列表
            var busslist = await dbClient.Queryable<W_Device>().Where(x => deviceBatchModel.codes.Contains(x.Id) && x.Businessid != emptyid).Select(x => x.Businessid).ToListAsync();
            if (deviceBatchModel.type == 1)
            {
                busslist.Add(deviceBatchModel.BusinessId);
                //如果是管理员分配
                if (currentUser.AccountType == (int)AccountType.platform)
                {
                    await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
                    {
                        Businessid = deviceBatchModel.BusinessId,
                        ActiveTime = DateTime.Now,
                        Status = (int)DeviceStatus.Run
                    }).Where(x => deviceBatchModel.codes.Contains(x.Id)).ExecuteCommandAsync();
                    await _businessService.InsertOrUpdateRealDataAsync();
                }
                else
                {
                    await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
                    {
                        Businessid = deviceBatchModel.BusinessId
                    }).Where(x => deviceBatchModel.codes.Contains(x.Id)).ExecuteCommandAsync();
                    busslist.Add(currentUser.BusinessId);
                }
                await _businessService.InsertOrUpdateRealDataAsync(busslist);
                return new ResultInfo(ResultState.SUCCESS, "分配成功");
            }
            else
            {
                deviceBatchModel.BusinessId = currentUser.AccountType != (int)AccountType.platform ? currentUser.BusinessId : Guid.Empty;
                //如果是管理员回收
                if (currentUser.AccountType == (int)AccountType.platform)
                {
                    await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
                    {
                        Businessid = deviceBatchModel.BusinessId,
                        ActiveTime = null,
                        Status = (int)DeviceStatus.WaitActive
                    }).Where(x => deviceBatchModel.codes.Contains(x.Id)).ExecuteCommandAsync();
                    await _businessService.InsertOrUpdateRealDataAsync();
                }
                else
                {
                    await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
                    {
                        Businessid = deviceBatchModel.BusinessId
                    }).Where(x => deviceBatchModel.codes.Contains(x.Id)).ExecuteCommandAsync();
                    busslist.Add(currentUser.BusinessId);
                }
                await _businessService.InsertOrUpdateRealDataAsync(busslist);
                return new ResultInfo(ResultState.SUCCESS, "回收成功");
            }
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DeviceSubmit> DetailAsync(Guid id)
        {
            var devicedata = await dbClient.Queryable<W_Device>().FirstAsync(x => x.Id == id);
            var pltdata = await repository.Change<W_SZDevice>().Context.Queryable<W_SZDevice>().FirstAsync(x => x.DeviceId == devicedata.Id);
            return new DeviceSubmit
            {
                DeviceType = devicedata.DeviceType,
                Secret = pltdata != null ? pltdata.Secret : "",
                SecretHash = pltdata != null ? pltdata.SecretHash : "",
                Address = devicedata.Address,
                Area = devicedata.Area,
                City = devicedata.City,
                DevId = pltdata != null ? pltdata.DevId : "",
                Ecode = devicedata.Ecode,
                FacEcode = devicedata.FacEcode,
                Name = devicedata.Name,
                NetType = devicedata.NetType,
                Province = devicedata.Province,
                Tare = devicedata.Tare,
                Remark = devicedata.Remark,
                Id = devicedata.Id
            };
        }

        /// <summary>
        /// 设备详情数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DeviceDetailS2Dto> DeviceDetailAsync(Guid id)
        {
            var devicedata = await dbClient.Queryable<W_DeviceData>().FirstAsync(x => x.DeviceId == id);
            var deviceresult = await dbClient.Queryable<W_DeviceResult>().FirstAsync(x => x.DeviceId == id);
            var device = await dbClient.Queryable<W_Device>().FirstAsync(x => x.Id == id);
            return new DeviceDetailS2Dto
            {
                Id = device.Id,
                Name = device.Name,
                Status = device.Status,
                LastStartTime = devicedata != null ? (devicedata.LastStartTime.HasValue ? devicedata.LastStartTime.ToString() : "-") : "-",
                LastBeatTime = devicedata != null ? (devicedata.LastBeatTime.HasValue ? devicedata.LastBeatTime.ToString() : "-") : "-",
                LastHeartTime = device.LastHeartTime,
                Latitude = devicedata.Latitude,
                Longitude = devicedata.Longitude,
                ActiveTime = device.ActiveTime,
                Address = device.Address,
                version = devicedata.Version,
                Tare = device.Tare,
                Ecode = device.Ecode,
                FacEcode = device.FacEcode
            };
        }

        /// <summary>
        /// 获取设备配置详情
        /// </summary>
        /// <param name="id">设备ID</param>
        /// <returns></returns>
        public async Task<W_DeviceConfig> GetConfigAsync(Guid id)
        {
            var data = await dbClient.Queryable<W_DeviceConfig>().FirstAsync(x => x.DeviceId == id);
            if (data == null)
            {
                data = new W_DeviceConfig();
            }
            return data;
        }

        /// <summary>
        /// 设备列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<DeviceList>> GetListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<W_Device>();
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(e =>
                {
                    if (!string.IsNullOrEmpty(e.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = e.Name,
                            ConditionalType = (ConditionalType)e.Type,
                            FieldValue = e.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            //针对非平台类型,则可以查看下面所有的子账户设备
            if (currentUser.AccountType != (int)AccountType.platform)
            {
                var sql = $"code like '{currentUser.BusinessCode}'+'%' and id = x.businessid";
                temquery = temquery.Where(x => SqlFunc.Subqueryable<W_Business>().Where(sql).Any());
            }
            string sorts = string.Format("{0} {1}", param.sort, param.order);
            var query = await temquery.OrderBy(sorts)
                .Select(x => new DeviceList
                {
                    Id = x.Id,
                    Name = x.Name,
                    Businessid = x.Businessid,
                    Address = x.Address,
                    Ecode = x.Ecode,
                    FacEcode = x.FacEcode,
                    CreateTime = x.CreateTime,
                    DeviceType = x.DeviceType,
                    LastHeartTime = x.LastHeartTime,
                    NetType = x.NetType,
                    Remark = x.Remark,
                    Status = x.Status,
                    InstallTime = x.InstallTime,
                    ActiveTime = x.ActiveTime,
                    Tare = x.Tare
                })
                .Mapper((it, cache) =>
                {
                    var allbuss = cache.Get(list =>
                    {
                        var ids = list.Where(e => e.Businessid != Guid.Empty).Select(e => e.Businessid).ToList();
                        return repository.Change<W_Business>().Context.Queryable<W_Business>().Where(e => ids.Contains(e.Id)).ToList();
                    });
                    var alldevicerealdata = cache.Get(list =>
                    {
                        var ids = list.Select(e => e.Id).ToList();
                        return repository.Change<W_DeviceRealData>().Context.Queryable<W_DeviceRealData>().Where(e => ids.Contains(e.DeviceId)).ToList();
                    });
                    //判断网络是否在线
                    if (it.LastHeartTime.HasValue && it.LastHeartTime.Value.AddMinutes(16) >= DateTime.Now)
                    {
                        it.NetStatus = (int)DeviceNetStatus.OnLine;
                    }
                    var devicerealdata = alldevicerealdata.FirstOrDefault(e => e.DeviceId == it.Id && e.BusinessId == it.Businessid);
                    if (devicerealdata != null)
                    {
                        it.TodayCount = devicerealdata.TodayCount;
                        it.TodayWeight = devicerealdata.TodayWeigth;
                        it.TotalCount = devicerealdata.TotalCount;
                        it.TotalWeight = devicerealdata.TotalWeight;
                    }
                    var alldevicedata = cache.Get(list =>
                    {
                        var ids = list.Select(e => e.Id).ToList();
                        return repository.Change<W_DeviceData>().Context.Queryable<W_DeviceData>().Where(e => ids.Contains(e.DeviceId)).ToList();
                    });
                    var devicedata = alldevicedata.FirstOrDefault(e => e.DeviceId == it.Id);
                    if (devicedata != null)
                    {
                        it.ICCID = devicedata.ICCID;
                        it.IMEI = devicedata.IMEI;
                        it.IMSI = devicedata.IMSI;
                        it.LastBeatTime = devicedata.LastBeatTime;
                        it.Longitude = devicedata.Longitude;
                        it.Latitude = devicedata.Latitude;
                        //判断网络是否在线
                        if (devicedata.LastBeatTime.HasValue && devicedata.LastBeatTime.Value.AddMinutes(16) >= DateTime.Now)
                        {
                            it.NetStatus = (int)DeviceNetStatus.OnLine;
                        }
                        it.sign = (devicedata.Sign.ToDouble() / (6 * 1.0)).ToString("f1");
                    }
                    it.BusinessName = allbuss.FirstOrDefault(e => e.Id == it.Businessid)?.Name;
                })
                 .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<DeviceList>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }

        /// <summary>
        /// 配置设备推送信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetConfigAsync(DeviceConfigC2SDto input)
        {
            if (!await dbClient.Queryable<W_Device>().AnyAsync(x => x.Id == input.Id))
            {
                return new ResultInfo(ResultState.FAIL, "设备未找到");
            }
            input.Body = input.Body.ToStr();
            input.Url = input.Url.ToLower();
            if (!input.Id.IsEmpty() && await dbClient.Queryable<W_DeviceConfig>().AnyAsync(x => x.DeviceId == input.Id))
            {
                await dbClient.Updateable<W_DeviceConfig>().SetColumns(x => new W_DeviceConfig
                {
                    Url = input.Url,
                    Body = input.Body
                }).Where(x => x.DeviceId == input.Id).ExecuteCommandAsync();
            }
            else
            {
                var insertdata = input.Adapt<W_DeviceConfig>();
                insertdata.DeviceId = input.Id;
                insertdata.CreateTime = DateTime.Now;
                await dbClient.Insertable(insertdata).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "配置成功");
        }

        /// <summary>
        /// 批量配置千灯镇商户推送
        /// </summary>
        /// <returns></returns>
        public async Task SetQDConfig()
        {
            string Body = string.Empty;
            string Url = "http://36.154.126.138:8817/api/third/postdata";
            var bid = Guid.Parse("08D99B4B-B02D-4E65-8D56-2FD16EC1716F");
            var alldevice = await dbClient.Queryable<W_Device>().Where(x => x.Businessid == bid).Select(x => new W_Device
            {
                Id = x.Id,
                FacEcode=x.FacEcode
            }).ToListAsync();
            foreach (var item in alldevice)
            {
                if (await dbClient.Queryable<W_DeviceConfig>().AnyAsync(x => x.DeviceId == item.Id))
                {
                    await dbClient.Updateable<W_DeviceConfig>().SetColumns(x => new W_DeviceConfig
                    {
                        Url = Url,
                        Body = Body
                    }).Where(x => x.DeviceId == item.Id).ExecuteCommandAsync();
                }
                else
                {
                    var insertdata = new W_DeviceConfig
                    {
                        DeviceId = item.Id,
                        Body = Body,
                        CreateTime = DateTime.Now,
                        Url = Url
                    };
                    await dbClient.Insertable(insertdata).ExecuteCommandAsync();
                }
            }
        }

        /// <summary>
        /// 设备状态修改
        /// </summary>
        /// <param name="id">设备ID</param>
        /// <param name="status">设备状态,0-停用,1-正常,2-激活</param>
        /// <returns></returns>
        public async Task<ResultInfo> SetStatusAsync(Guid id, int status)
        {
            if (!await dbClient.Queryable<W_Device>().AnyAsync(x => x.Id == id))
            {
                return new ResultInfo(ResultState.FAIL, "设备未找到");
            }
            await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
            {
                Status = status
            }).Where(x => x.Id == id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "设备状态已更新");
        }

        /// <summary>
        /// 信息提交
        /// </summary>
        /// <param name="role"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SubmitFormAsync(DeviceSubmit role)
        {
            role.Name = role.Name.ToStr();
            role.FacEcode = role.FacEcode.ToStr();
            role.Ecode = role.Ecode.ToStr();
            role.Remark = role.Remark.ToStr();
            role.Province = role.Province.ToStr();
            role.City = role.City.ToStr();
            role.Area = role.Area.ToStr();
            role.Address = role.Address.ToStr();
            role.Secret = role.Secret.ToStr();
            role.SecretHash = role.SecretHash.ToStr();
            role.DevId = role.DevId.ToStr();
            if (role.Id != Guid.Empty)
            {
                //检查序列号是否已存在
                if (await dbClient.Queryable<W_Device>().AnyAsync(x => x.FacEcode == role.FacEcode && x.Id != role.Id))
                {
                    return new ResultInfo() { code = ResultState.FAIL, message = "此序列号已存在!" };
                }
                //检查机器码是否已存在
                if (await dbClient.Queryable<W_Device>().AnyAsync(x => x.Ecode == role.Ecode && x.Id != role.Id))
                {
                    return new ResultInfo() { code = ResultState.FAIL, message = "此设备码已存在!" };
                }
                await dbClient.Updateable<W_Device>().SetColumns(x => new W_Device
                {
                    DeviceType = role.DeviceType,
                    Address = role.Address,
                    Area = role.Area,
                    City = role.City,
                    Ecode = role.Ecode,
                    FacEcode = role.FacEcode,
                    Name = role.Name,
                    Remark = role.Remark,
                    NetType = role.NetType,
                    Province = role.Province,
                    Tare = role.Tare
                }).Where(x => x.Id == role.Id).ExecuteCommandAsync();
                //更新平台信息
                var tdbclient = repository.Change<W_SZDevice>().Context;
                if (!await tdbclient.Queryable<W_SZDevice>().AnyAsync(x => x.DeviceId == role.Id))
                {
                    if (!string.IsNullOrEmpty(role.Secret) && !string.IsNullOrEmpty(role.SecretHash) && !string.IsNullOrEmpty(role.DevId))
                    {
                        await tdbclient.Insertable<W_SZDevice>(new W_SZDevice
                        {
                            DeviceId = role.Id,
                            Secret = role.Secret,
                            SecretHash = role.SecretHash,
                            DevId = role.DevId
                        }).ExecuteCommandAsync();
                    }
                }
                else
                {
                    await tdbclient.Updateable<W_SZDevice>().SetColumns(x => new W_SZDevice
                    {
                        Secret = role.Secret,
                        SecretHash = role.SecretHash,
                        DevId = role.DevId
                    }).Where(x => x.DeviceId == role.Id).ExecuteCommandAsync();
                }
                return new ResultInfo() { code = ResultState.SUCCESS, message = "修改成功!" };
            }
            else
            {
                //检查序列号是否已存在
                if (await dbClient.Queryable<W_Device>().AnyAsync(x => x.FacEcode == role.FacEcode))
                {
                    return new ResultInfo() { code = ResultState.FAIL, message = "此序列号已存在!" };
                }
                //检查机器码是否已存在
                if (await dbClient.Queryable<W_Device>().AnyAsync(x => x.Ecode == role.Ecode))
                {
                    return new ResultInfo() { code = ResultState.FAIL, message = "此设备码已存在!" };
                }
                role.CreateTime = DateTime.Now;
                role.Status = (int)DeviceStatus.WaitActive;
                role.Id = IDGen.NextID();
                await dbClient.Insertable<W_Device>(new W_Device
                {
                    Id = role.Id,
                    Status = role.Status,
                    ActiveTime = role.ActiveTime,
                    Address = role.Address,
                    Area = role.Area,
                    Businessid = role.Businessid,
                    City = role.City,
                    CreateTime = role.CreateTime,
                    DeviceType = role.DeviceType,
                    Ecode = role.Ecode,
                    FacEcode = role.FacEcode,
                    Remark = role.Remark,
                    InstallTime = role.InstallTime,
                    LastHeartTime = role.LastHeartTime,
                    Name = role.Name,
                    NetType = role.NetType,
                    Province = role.Province,
                    Tare = role.Tare
                }).ExecuteCommandAsync();
                //更新平台信息
                if (!string.IsNullOrEmpty(role.Secret) && !string.IsNullOrEmpty(role.SecretHash) && !string.IsNullOrEmpty(role.DevId))
                {
                    var tdbclient = repository.Change<W_SZDevice>().Context;
                    await tdbclient.Insertable<W_SZDevice>(new W_SZDevice
                    {
                        DeviceId = role.Id,
                        Secret = role.Secret,
                        SecretHash = role.SecretHash,
                        DevId = role.DevId
                    }).ExecuteCommandAsync();
                }
                await _businessService.InsertOrUpdateRealDataAsync();
                return new ResultInfo() { code = ResultState.SUCCESS, message = "添加成功!" };
            }
        }
    }
}