using GraphQL;
using LY.App.Common.Redis;
using LY.App.Device;
using LY.App.Extensions.DI;
using LY.App.Model;
using Mapster;
using Newtonsoft.Json;
using SqlSugar;
namespace LY.App.Service
{
    /// 
    /// 设备服务
    /// 
    [ServiceInjection(InjectionType.Transient)]
    public class DeviceService
    {
        private readonly SqlSugarClient _db;
        private readonly RedisService _redisService;
        private readonly AlarmService _alarmService;
        private readonly DeviceManager deviceManager = DeviceManager.Instance;
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        /// 
        public DeviceService(SqlSugarClient db, RedisService redisService, AlarmService alarmService)
        {
            _db = db;
            _redisService = redisService;
            _alarmService = alarmService;
        }
        /// 
        /// 分页查询
        /// 
        /// 
        /// 
        /// 
        /// 
        public async Task List(int pageNum, int pageSize, string key)
        {
            RefAsync total = 0;
            var items = await _db.Queryable()
                .Where(s => s.IsDeleted == false)
                .WhereIF(!string.IsNullOrEmpty(key), s => s.Name.Contains(key) || s.DeviceSN.Contains(key))
                .OrderByDescending(s => s.Id)
                .ToPageListAsync(pageNum, pageSize, total);
            return new ApiResult()
            {
                data = new
                {
                    total = total.Value,
                    items
                }
            };
        }
        /// 
        /// 新增设备
        /// 
        /// 
        /// 
        public async Task Add(AddDevice input)
        {
            var entity = input.Adapt();
            var id = await _db.Insertable(entity).ExecuteReturnSnowflakeIdAsync();
            entity.Id = id;
            await AddDevice2Manager(entity);
            var key = RedisKeyList.DeviceInfo(entity.DeviceSN);
            await _redisService.SetAsync(key, entity, TimeSpan.FromDays(10));
            return new ApiResult()
            {
                code = 0,
                msg = "success"
            };
        }
        /// 
        /// 获取协议列表
        /// 
        /// 
        public Task ProtocolTypeList()
        {
            var dict = new Dictionary();
            foreach (ProtocolType protocol in Enum.GetValues(typeof(ProtocolType)))
            {
                dict.Add((int)protocol, protocol.ToString());
            }
            return Task.FromResult(new ApiResult()
            {
                data = dict
            });
        }
        /// 
        /// 更新设备信息
        /// 
        /// 
        /// 
        public async Task updata(UpdateDevice input)
        {
            var entity = input.Adapt();
            await _db.Updateable(entity).ExecuteCommandAsync();
            await deviceManager.RemoveDevice(entity.Id);
            await AddDevice2Manager(entity);
            return new ApiResult()
            {
                code = 0,
                msg = "success"
            };
        }
        /// 
        /// 删除设备
        /// 
        /// 
        /// 
        public async Task delete(long Id)
        {
            var entity = await _db.Queryable().FirstAsync(s => s.Id == Id);
            entity.IsDeleted = true;
            await _db.Updateable(entity).ExecuteCommandAsync();
            await deviceManager.RemoveDevice(entity.Id);
            return new ApiResult()
            {
                code = 0,
                msg = "success"
            };
        }
        /// 
        /// 取单个设备详情
        /// 
        /// 
        /// 
        public async Task detail(long Id)
        {
            return await _db.Queryable()
                .FirstAsync(s => s.Id == Id);
        }
        /// 
        /// 获取首页数据
        /// 
        /// 
        public async Task> All()
        {
            var result = await _db.Queryable()
               .Where(s => s.IsDeleted == false)
               .ToListAsync();
            return result;
        }
        private Task AddDevice2Manager(DeviceEntity entity)
        {
            var device = new Device.Device()
            {
                Id = entity.Id,
                Port = entity.Port,
                GraphQlEndpoint = entity.GraphQlEndpoint,
                Topic = entity.Topic,
                IpAddress = entity.ip,
                Protocol = entity.Protocol,
                username = entity.account,
                password = entity.password,
                DataReceived = async (data) =>
                {
                    try
                    {
                        var input = JsonConvert.DeserializeObject(data);
                        //      Console.WriteLine($"rev data:{data}");
                        await _alarmService.AddAlarm(input);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"error:{ex.Message},data:{data}");
                    }
                }
            };
            deviceManager.AddDevice(device);
            return Task.CompletedTask;
        }
        /// 
        /// 初始化,加载所有设备
        /// 
        /// 
        public async Task Init()
        {
            var devices = await _db.Queryable().Where(s => s.IsDeleted == false).ToListAsync();
            foreach (var item in devices)
            {
                var key = RedisKeyList.DeviceInfo(item.DeviceSN);
                await _redisService.SetAsync(key, item, TimeSpan.FromDays(100));
                await AddDevice2Manager(item);
            }
            // 加载防区信息
            var position = await _db.Queryable()
                .Where(s => s.IsDeleted == false).ToListAsync();
            foreach (var item in position)
            {
                var key = RedisKeyList.PositioinRegion(item.Id);
                await _redisService.SetAsync(key, item);
            }
            // 加载白名单信息
            var whithlist = await _db.Queryable()
                .Where(s => s.IsDeleted == false).ToListAsync();
            foreach (var item in whithlist)
            {
                var key = RedisKeyList.white_list(item.sn);
                await _redisService.SetAsync(key, item);
            }
        }
    }
}