using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Spreadsheet;
using Hopetry.App.SugarModel.CommonModel;
using Infrastructure;
using Infrastructure.Extensions;
using Infrastructure.Utilities;
using Jiguang.JPush;
using Jiguang.JPush.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Common;
using OpenAuth.App.Const;
using OpenAuth.App.Interface;
using OpenAuth.App.Response;
using OpenAuth.App.ServiceApp.FireManagement.Request;
using OpenAuth.App.ServiceApp.FireManagement.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.FireManagement;
using Org.BouncyCastle.Ocsp;
using SqlSugar;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using Hopetry.App.SugarModel.FeiXianModel.YingJingJu;
using Infrastructure.Helpers;
using Yitter.IdGenerator;
using static Org.BouncyCastle.Math.EC.ECCurve;
using DocumentFormat.OpenXml.Wordprocessing;
using Newtonsoft.Json.Linq;
using DocumentFormat.OpenXml.Vml.Wordprocessing;
using Infrastructure.Cache;

namespace OpenAuth.App.ServiceApp.FireManagement
{
    public class FireManagementApp : SqlSugarBaseApp<FmFireclueTask, SugarDbContext>
    {
        private ClientWebSocket _socket;
        private IConfiguration _configuration;
        IOptions<KikvisionConfig> _options;
        IOptions<KikvisionConfig2> _options2;
        IOptions<JPushClientConfig> _jpoptions;
        private ICacheContext _cacheContext;

        public FireManagementApp(IConfiguration configuration, IOptions<KikvisionConfig> options, IOptions<KikvisionConfig2> options2,
            IOptions<JPushClientConfig> jpoptions, ICacheContext cacheContext, ISugarUnitOfWork<SugarDbContext> unitWork,
            ISimpleClient<FmFireclueTask> repository, IAuth auth) : base(unitWork, repository, auth)
        {
            _auth = auth;
            _options = options;
            _options2 = options2;
            _configuration = configuration;
            _jpoptions = jpoptions;
            _cacheContext = cacheContext;
        }

        /// <summary>
        /// 下发防火线索任务
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<Response<bool>> IssuedFireClueTask(FmFireclueTask info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var userId = _auth.GetCurrentUser().User.Id;
                info.Id = YitIdHelper.NextId();
                info.State = (int)TaskState.待接收;
                info.TaskTime = DateTime.Now;
                info.IsDelete = false;
                await db.FmFireclueTask.InsertAsync(info);
                List<FmFireTaskUser> fftuList = new List<FmFireTaskUser>();
                if (info.RecipientUsers == null || info.RecipientUsers.Count == 0)
                {
                    var userList = await db.User.AsQueryable().Where(r => r.Status == 0).ToListAsync();
                    userList.ForEach(user =>
                    {
                        FmFireTaskUser fftu = new FmFireTaskUser
                        {
                            Id = YitIdHelper.NextId(),
                            UserId = user.Id.ToString(),
                            TaskId = info.Id,
                            ReceiveTime = DateTime.Now,
                            State = (int)TaskState.待接收
                        };
                        fftuList.Add(fftu);
                    });
                }
                else
                {
                    info.RecipientUsers.ForEach(user =>
                    {
                        FmFireTaskUser fftu = new FmFireTaskUser
                        {
                            Id = YitIdHelper.NextId(),
                            UserId = user,
                            TaskId = info.Id,
                            ReceiveTime = DateTime.Now,
                            State = (int)TaskState.待接收
                        };
                        fftuList.Add(fftu);
                    });
                }

                await db.FmFireTaskUser.InsertRangeAsync(fftuList);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = info.Fireclueid,
                    Title = "任务下发",
                    CreateTime = DateTime.Now,
                    CreateId = userId,
                    Content = info.Content
                });
                if (db.Commit())
                {
                    //// websocket 通讯
                    //WebSocketModel wsModel = new WebSocketModel
                    //{
                    //    Module = "任务下发",
                    //    Data = info
                    //};
                    //SendSocketMessage(wsModel);
                    JPushInfo("任务下发", info.Id);
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //删除任务
        public async Task<Response<bool>> DeleteTask(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var userId = _auth.GetCurrentUser().User.Id;
                var taskinfo = await db.FmFireclueTask.AsQueryable().FirstAsync(r => r.Id == id);
                await db.FmFireclueTask.UpdateAsync(r => new FmFireclueTask
                {
                    IsDelete = true
                }, r => r.Id == id);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = taskinfo.Fireclueid,
                    Title = "任务删除",
                    CreateTime = DateTime.Now,
                    CreateId = userId,
                    Content = "删除任务"
                });
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //更新任务状态
        public async Task<Response<bool>> ReceiveFireClueTask(long taskid, int state, string recipient)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                await db.FmFireTaskUser.UpdateAsync(r => new FmFireTaskUser
                {
                    State = state,
                    ReceiveTime = DateTime.Now,
                }, r => r.TaskId == taskid && r.UserId == recipient);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //更新任务图片或者新增线索
        public async Task<Response<bool>> ReceiveTaskImage(string info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<ReciveTaskInfo>(info);
                if (obj != null)
                {
                    var fireInfo = await db.FmFireclueTask.GetFirstAsync(r => r.Id == obj.taskid);
                    var imagepath = fireInfo.Image == null ? obj.path : fireInfo.Image + "," + obj.path;
                    await db.FmFireclueTask.UpdateAsync(r => new FmFireclueTask
                    {
                        Image = imagepath
                    }, r => r.Id == obj.taskid);
                }
                else
                {
                    //新增线索信息
                }

                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        /// <summary>
        /// 从态势感知平台添加无人机上报火情线索
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<Response<bool>> AddFireClueInfoUAV(string info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<ReciveFireClueInfo>(info);
                FmFireclueInfo fm = new FmFireclueInfo();
                fm.Id = YitIdHelper.NextId();
                fm.State = (int)State.上报;
                fm.ReportTime = DateTime.Now;
                fm.Lat = obj.Lat;
                fm.Lng=obj.Lng;
                fm.Address=obj.Address;
                fm.AreaName=obj.AreaName;
                fm.Image=obj.Image;
                fm.SourceType = 3;
                fm.ReportPerson = obj.ReportPerson;
                fm.Describe=obj.Describe;
                fm.DegreeType = obj.DegreeType;
                var today = DateTime.Now.Date;
                var tomorrow = today.AddDays(1);
                var exitinfo = db.FmFireclueInfo
                    .AsQueryable()
                    .Count(a => a.ReportTime >= today && a.ReportTime < tomorrow);
                string excount = exitinfo.ToString("D3");
                string sourceType = fm.SourceType switch
                {
                    1 => "R",
                    2 => "J",
                    3 => "W",
                    4 => "R",
                    5 => "G",
                    6 => "Y",
                    _ => "R"
                };

                // 生成线索编号
                fm.ClueNo = $"LH{DateTime.Now:yyyyMMdd}{excount}{sourceType}";
                await db.FmFireclueInfo.InsertAsync(fm);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = fm.Id,
                    Title = "无人机火情线索上报",
                    CreateTime = DateTime.Now,
                    CreateId = fm.CreateId,
                    Content = fm.Describe
                });
                if (db.Commit())
                {
                    JPushInfo("火情信息", 0);
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        class ReciveTaskInfo
        {
            public long taskid { get; set; }
            public string path { get; set; }
        }

        /// <summary>
        /// 查询下发人员
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public async Task<Response<List<SysUserResp>>> LoadFireClueUser(string username, string unitname)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var users = await db.User.AsQueryable()
                    .WhereIF(!string.IsNullOrEmpty(username), r => r.Name.Contains(username))
                    .WhereIF(!string.IsNullOrEmpty(unitname), r => r.UnitName.Contains(username))
                    .Where(r => r.Status == 0)
                    .Select(r => new SysUserResp
                    {
                        Id = r.Id,
                        Name = r.Name
                    }).ToListAsync();
                return new Response<List<SysUserResp>> { Result = users };
            }
        }

        /// <summary>
        /// 查询任务列表--后台使用
        /// </summary>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FmFireclueTask>>>> GetTaskPageList(FireClueTaskReq req)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var tasks = await db.FmFireclueTask.AsQueryable()
                    .Where(r=>r.IsDelete == false)
                    .Where(r => r.IsDelete == false)
                    .WhereIF(req.state!=null,r=>r.State==req.state)
                    .WhereIF(req.type!=null,r=>r.Type==req.type)
                    .WhereIF(req.tasktimebegin!=null&&req.tasktimeend!=null,r=>r.TaskTime>=req.tasktimebegin&&r.TaskTime<=req.tasktimeend)
                    .LeftJoin<FmFireclueInfo>((r,f)=>r.Fireclueid==f.Id)
                    .WhereIF(!string.IsNullOrEmpty(req.name),(r,f)=>r.Content.Contains(req.name)||f.Describe.Contains(req.name))
                    .ToPageListAsync(req.page, req.limit, totalNumber);
                return new Response<PageInfo<List<FmFireclueTask>>>
                {
                    Result = new PageInfo<List<FmFireclueTask>> { Items = tasks, Total = totalNumber }
                };
            }
        }


        /// <summary>
        /// 查询任务列表
        /// </summary>
        /// <returns></returns>
        public async Task<Response<List<FmFireclueTask>>> GetTaskList()
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var tasks = await db.FmFireclueTask.AsQueryable()
                    .Where(r => r.IsDelete == false)
                    .ToListAsync();
                return new Response<List<FmFireclueTask>> { Result = tasks };
            }
        }

        /// <summary>
        /// 任务详情
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        public async Task<Response<FireClueTaskResp>> LoadFireTaskInfoById(long id, string userid)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var info = await db.FmFireclueTask.AsQueryable()
                    .LeftJoin<SysUser>((a, b) => a.TaskUser == b.Id.ToString())
                    .Where((a, b) => a.Id == id)
                    .Select((a, b) => new FireClueTaskResp()
                    {
                        Id = a.Id,
                        Content = a.Content,
                        Lat = a.Lat,
                        Lng = a.Lng,
                        Address = a.Address,
                        State = a.State,
                        TaskUser = a.TaskUser,
                        TaskTime = a.TaskTime,
                        CompleteTime = a.CompleteTime,
                        TaskUserName = b.Name,
                        Audio = a.Audio,
                        Image = a.Image,
                    })
                    .Mapper(a => a.StateName = ((TaskState)a.State).GetDescription())
                    .FirstAsync();
                var rep = db.FmFireTaskUser.AsQueryable().Where(r => r.UserId == userid && r.TaskId == id).First();
                if (rep != null)
                {
                    info.State = rep.State;
                    info.StateName = ((TaskState)rep.State).GetDescription();
                }

                return new Response<FireClueTaskResp> { Result = info };
            }
        }


        /// <summary>
        /// 查询人员单位信息
        /// </summary>
        /// <returns></returns>
        public async Task<Response<List<FmUserUnit>>> GetUserUnit()
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var userunit = await db.FmUserUnit.AsQueryable().ToListAsync();
                return new Response<List<FmUserUnit>> { Result = userunit };
            }
        }

        #region 单位管理

        //添加人员单位
        public async Task<Response<bool>> AddUserUnit(FmUserUnit info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                info.Id = YitIdHelper.NextId();
                await db.FmUserUnit.InsertAsync(info);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //编辑人员单位
        public async Task<Response<bool>> EditUserUnit(FmUserUnit info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                await db.FmUserUnit.UpdateAsync(info);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //获取单个人员单位
        public async Task<Response<FmUserUnit>> LoadUserUnitById(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var info = await db.FmUserUnit.AsQueryable().FirstAsync(r => r.Id == id);
                return new Response<FmUserUnit> { Result = info };
            }
        }

        //删除人员单位
        public async Task<Response<bool>> DeleteUserUnit(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                await db.FmUserUnit.DeleteAsync(r => r.Id == id);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }


        public Response<bool> FireUserUnitUpload(IFormFileCollection formFiles)
        {
            var user = _auth.GetCurrentUser().User;
            IFormFile file = formFiles[0];
            Response<bool> response = new Response<bool>();
            try
            {
                //存储文件到服务器
                if (file != null)
                {
                    if (file.FileName.IndexOf(".xls") > 0 || file.FileName.IndexOf(".xlsx") > 0)
                    {
                        //数据库导入
                        IWorkbook workbook = null;
                        if (file.FileName.IndexOf(".xlsx") > 0)
                        {
                            using (var stream = file.OpenReadStream())
                            {
                                workbook = new XSSFWorkbook(stream); //excel的版本2007
                            }
                        }
                        else if (file.FileName.IndexOf(".xls") > 0)
                        {
                            using (var stream = file.OpenReadStream())
                            {
                                workbook = new HSSFWorkbook(stream); //excel的版本2003
                            }
                        }

                        ISheet sheet;
                        sheet = workbook.GetSheetAt(0);
                        List<FmUserUnit> fulist = new List<FmUserUnit>();
                        if (sheet != null)
                        {
                            IRow firstRow = sheet.GetRow(0);
                            string name = firstRow.GetCell(0).ToString();
                            //最后一列的标号
                            int rowCount = sheet.LastRowNum;
                            for (int i = 1; i <= rowCount; i++)
                            {
                                IRow row = sheet.GetRow(i);
                                if (row == null || string.IsNullOrEmpty(row.GetCell(0).ToString())) continue;
                                FmUserUnit fu = new FmUserUnit();
                                fu.Id = YitIdHelper.NextId();
                                fu.UnitName = row.GetCell(1).ToString();
                                fu.UnitType = row.GetCell(2).ToString();
                                fu.Description = row.GetCell(3).ToString();
                                fu.CreateTime = DateTime.Now;
                                fu.CreateUserId = user.Id.ToString();
                                fulist.Add(fu);
                            }
                        }

                        using (var db = base.UnitWork.CreateContext())
                        {
                            db.FmUserUnit.InsertRange(fulist);
                            if (db.Commit())
                            {
                                return new Response<bool> { Result = true, Message = "导入成功" };
                            }
                            else
                            {
                                return new Response<bool> { Result = false, Message = "导入失败" };
                            }
                        }
                    }
                    else
                    {
                        response.Result = false;
                        response.Message = "上传文件类型错误，请上传Excel文件";
                        response.Code = 300;
                    }
                }
            }
            catch (Exception ex)
            {
                response.Result = false;
                response.Code = 400;
                response.Message = "上传文件类型错误";
            }

            return response;
        }

        #endregion

        #region 火情线索

        public async Task<Response<bool>> AddFireClueInfo(FmFireclueInfo info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                info.Id = YitIdHelper.NextId();
                info.State = (int)State.上报;
                info.ReportTime = DateTime.Now;
                var today = DateTime.Now.Date;
                var tomorrow = today.AddDays(1);
                var exitinfo = db.FmFireclueInfo
                    .AsQueryable()
                    .Count(a => a.ReportTime >= today && a.ReportTime < tomorrow);
                string excount = exitinfo.ToString("D3");
                string sourceType = info.SourceType switch
                {
                    1 => "R",
                    2 => "J",
                    3 => "W",
                    4 => "R",
                    5 => "G",
                    6 => "Y",
                    _ => "R"
                };

                // 生成线索编号
                info.ClueNo = $"LH{DateTime.Now:yyyyMMdd}{excount}{sourceType}";
                await db.FmFireclueInfo.InsertAsync(info);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = info.Id,
                    Title = "火情线索上报",
                    CreateTime = DateTime.Now,
                    CreateId = info.CreateId,
                    Content = info.Describe
                });
                if (db.Commit())
                {
                    JPushInfo("火情信息", 0);
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        public async Task<Response<bool>> AddFireClueInfoGZFK(FmFireclueInfo info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                info.Id = YitIdHelper.NextId();
                info.State = (int)State.上报;
                info.ReportTime = DateTime.Now;
                
                var today = DateTime.Now.Date;
                var tomorrow = today.AddDays(1);
                var exitinfo = db.FmFireclueInfo
                    .AsQueryable()
                    .Count(a => a.ReportTime >= today && a.ReportTime < tomorrow);
                string excount = exitinfo.ToString("D3");
                string sourceType = info.SourceType switch
                {
                    1 => "R",
                    2 => "J",
                    3 => "W",
                    4 => "R",
                    5 => "G",
                    6 => "Y",
                    _ => "R"
                };

                // 生成线索编号
                info.ClueNo = $"LH{DateTime.Now:yyyyMMdd}{excount}{sourceType}";
                await db.FmFireclueInfo.InsertAsync(info);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = info.Id,
                    Title = "火情线索上报",
                    CreateTime = DateTime.Now,
                    CreateId = info.CreateId,
                    Content = info.Describe
                });
                if (db.Commit())
                {
                    JPushInfo("火情信息", 0);
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        /// <summary>
        /// 查询火情线索
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Response<FmFireclueInfo>> LoadClueInfoById(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var info = await db.FmFireclueInfo.AsQueryable()
                    .FirstAsync(r => r.Id == id);
                return new Response<FmFireclueInfo> { Result = info };
            }
        }

        public async Task<Response<dynamic>> LoadClueWithInfoById(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var clueInfo = await db.FmFireclueInfo.AsQueryable()
                    .FirstAsync(r => r.Id == id);
                //查找摄像头
                var sqlStr = $@"select ""Id"",""Name"",""SerialNumber"" from fm_camera 
                        where ST_DWithin(ST_GeographyFromText('POINT({clueInfo.Lng} {clueInfo.Lat})'),
                        ST_GeographyFromText('POINT('||""Lng""||' '||""Lat""||')'),1000)=true";
                var cameraInfo = await db.Db.Ado.GetDataTableAsync(sqlStr);
                var endInfo = new
                {
                    clueInfo,
                    cameraInfo,
                };
                return new Response<dynamic> { Result = endInfo };
            }
        }

        //查询火情线索列表
        public async Task<Response<List<FmFireclueInfo>>> GetFireClueList()
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var list = await db.FmFireclueInfo.AsQueryable().Where(r => r.State == 1).ToListAsync();
                return new Response<List<FmFireclueInfo>> { Result = list };
            }
        }

        /// <summary>
        /// 查询火情线索列表--后台使用
        /// </summary>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FmFireclueInfo>>>> GetFireCluePageList(FireClueInfoReq req)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var infos = await db.FmFireclueInfo.AsQueryable()
                    .WhereIF(req.state != null, r => r.State == req.state)
                    .WhereIF(req.sourcetype != null, r => r.SourceType == req.sourcetype)
                    .WhereIF(req.reporttimebegin != null && req.reporttimeend != null, r => r.ReportTime >= req.reporttimebegin && r.ReportTime <= req.reporttimeend)
                    .WhereIF(!string.IsNullOrEmpty(req.name), r=> r.Describe.Contains(req.name))
                    .WhereIF(!string.IsNullOrEmpty(req.adress), r=> r.Address.Contains(req.adress))                
                    .ToPageListAsync(req.page, req.limit, totalNumber);
                return new Response<PageInfo<List<FmFireclueInfo>>>
                {
                    Result = new PageInfo<List<FmFireclueInfo>> { Items = infos, Total = totalNumber }
                };
            }
        }

        /// <summary>
        /// 修改火情线索状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public async Task<Response<bool>> UpdatFireState(long id, int state)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var userId = _auth.GetCurrentUser().User.Id;
                await db.FmFireclueInfo.UpdateAsync(r => new FmFireclueInfo
                {
                    State = state,
                    ModifyTime = DateTime.Now,
                    ModifyId = userId
                }, r => r.Id == id);
                await db.FmFireclueinfoLog.InsertAsync(new FmFireclueinfoLog
                {
                    Id = YitIdHelper.NextId(),
                    Fireclueid = id,
                    Title = "修改火情线索状态",
                    CreateTime = DateTime.Now,
                    CreateId = userId,
                    Content = "火情线索状态变化"
                });
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        /// <summary>
        /// 添加火情日志 
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<Response<bool>> AddFireClueLogInfo(FmFireclueinfoLog info)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var userId = _auth.GetCurrentUser().User.Id;
                info.CreateId = userId;
                info.CreateTime = DateTime.Now;
                await db.FmFireclueinfoLog.InsertAsync(info);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        //按月统计火情线索
        public async Task<Response<List<FireInfoForChart>>> GetFireClueStatistics(int type)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                if (type == 1)
                {
                    DateTime firstDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                    var list = await db.FmFireclueInfo.AsQueryable()
                        //.Where(r => r.State == 1)
                        .Where(r => r.ReportTime >= firstDayOfMonth)
                        .GroupBy(r => new { r.ReportTime.Day })
                        .Select(r => new FireInfoForChart
                        {
                            DateTime = r.ReportTime.Day.ToString() + "日",
                            Count = SqlFunc.AggregateCount(r.Id)
                        }).ToListAsync();
                    return new Response<List<FireInfoForChart>> { Result = list };
                }
                else
                {
                    DateTime firstDayOfYear = new DateTime(DateTime.Now.Year, 1, 1);
                    var list = await db.FmFireclueInfo.AsQueryable()
                        //.Where(r => r.State == 1)
                        .Where(r => r.ReportTime >= firstDayOfYear)
                        .GroupBy(r => new { r.ReportTime.Month })
                        .Select(r => new FireInfoForChart
                        {
                            DateTime = r.ReportTime.Month.ToString() + "月",
                            Count = SqlFunc.AggregateCount(r.Id)
                        }).ToListAsync();
                    return new Response<List<FireInfoForChart>> { Result = list };
                }
            }
        }

        public async Task<Response<List<FireInfoStateForChart>>> GetFireClueStatisticsByState(int type,List<int> sourcetype)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                //if (type == 1)
                //{
                //    DateTime firstDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                //    var list = await db.FmFireclueInfo.AsQueryable()
                //        .Where(r => r.ReportTime >= firstDayOfMonth)
                //        .GroupBy(r => new { r.ReportTime.Day })
                //        .Select(r => new FireInfoStateForChart
                //        {
                //            DateTime = r.ReportTime.Day.ToString() + "日",
                //            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                //            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                //        }).ToListAsync();
                //    return new Response<List<FireInfoStateForChart>> { Result = list };
                //}
                //else if (type == 2)
                //{
                //    DateTime firstDayOfYear = new DateTime(DateTime.Now.Year, 1, 1);
                //    var list = await db.FmFireclueInfo.AsQueryable()
                //        .Where(r => r.ReportTime >= firstDayOfYear)
                //        .GroupBy(r => new { r.ReportTime.Month })
                //        .Select(r => new FireInfoStateForChart
                //        {
                //            DateTime = r.ReportTime.Month.ToString() + "月",
                //            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                //            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                //        }).ToListAsync();
                //    return new Response<List<FireInfoStateForChart>> { Result = list };
                //}
                //else
                //{
                //    DateTime firstDayOfYear = DateTime.Now.AddYears(-3);
                //    var list = await db.FmFireclueInfo.AsQueryable()
                //        .Where(r => r.ReportTime >= firstDayOfYear)
                //        .GroupBy(r => new { r.ReportTime.Year })
                //        .Select(r => new FireInfoStateForChart
                //        {
                //            DateTime = r.ReportTime.Year.ToString() + "年",
                //            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                //            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                //        }).ToListAsync();
                //    return new Response<List<FireInfoStateForChart>> { Result = list };
                //}

                if (type == 1)
                {
                    // 计算14天的日期范围
                    DateTime startDate = DateTime.Now.AddDays(-14).Date;
                    DateTime endDate = DateTime.Now.Date;

                    // 生成14天的日期列表
                    var dateRange = Enumerable.Range(0, (endDate - startDate).Days + 1)
                        .Select(offset => startDate.AddDays(offset))
                        .Select(date => new
                        {
                            Date = date,
                            DayString = date.Month.ToString() + "." + date.Day.ToString()
                        })
                        .ToList();

                    // 查询实际数据
                    var dataQuery = await db.FmFireclueInfo.AsQueryable()
                        .WhereIF(sourcetype.Count>0,r=>sourcetype.Contains(r.SourceType))
                        .Where(r => r.ReportTime >= startDate && r.ReportTime <= endDate)
                        .GroupBy(r => new { r.ReportTime.Date })
                        .Select(r => new FireInfoState
                        {
                            Date = r.ReportTime.Date,
                            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                        }).ToListAsync();

                    // 左连接，确保所有日期都显示
                    var list = (from date in dateRange
                                join data in dataQuery on date.Date equals data.Date into gj
                                from subData in gj.DefaultIfEmpty()
                                orderby date.Date ascending
                                select new FireInfoStateForChart
                                {
                                    DateTime = date.DayString,
                                    TreatedCount = subData?.TreatedCount ?? 0,
                                    UntreatedCount = subData?.UntreatedCount ?? 0
                                })
                               .ToList();

                    return new Response<List<FireInfoStateForChart>> { Result = list };
                }
                else if (type == 2)
                {
                    // 计算日期范围
                    var now = DateTime.Now;
                    var startDate = new DateTime(now.Year, now.Month, 1).AddMonths(-11);
                    var endDate = new DateTime(now.Year, now.Month, 1).AddMonths(1).AddDays(-1);

                    // 生成月份列表
                    var months = Enumerable.Range(0, 12)
                        .Select(i => new
                        {
                            Year = startDate.AddMonths(i).Year,
                            Month = startDate.AddMonths(i).Month,
                            Display = FormatMonthDisplay(startDate.AddMonths(i))
                        })
                        .ToList();

                    // 查询数据
                    var data = await db.FmFireclueInfo.AsQueryable()
                        .WhereIF(sourcetype.Count > 0, r => sourcetype.Contains(r.SourceType))
                        .Where(r => r.ReportTime >= startDate && r.ReportTime <= endDate)
                        .GroupBy(r => new { r.ReportTime.Year, r.ReportTime.Month })
                        .Select(r => new
                        {
                            Year = r.ReportTime.Year,
                            Month = r.ReportTime.Month,
                            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                        })
                        .ToListAsync();

                    // 使用LINQ左连接
                    var result = (from month in months
                                  join d in data
                                  on new { month.Year, month.Month } equals new { d.Year, d.Month } into gj
                                  from subData in gj.DefaultIfEmpty()
                                  orderby month.Year, month.Month
                                  select new FireInfoStateForChart
                                  {
                                      DateTime = month.Display,
                                      TreatedCount = subData?.TreatedCount ?? 0,
                                      UntreatedCount = subData?.UntreatedCount ?? 0
                                  }).ToList();
                    return new Response<List<FireInfoStateForChart>> { Result = result };
                }
                else
                {
                    // 计算统计年份范围
                    int currentYear = DateTime.Now.Year;
                    int startYear = currentYear - 5 + 1;

                    // 生成年份范围
                    var years = Enumerable.Range(startYear, 5)
                        .Select(y => y)
                        .ToList();

                    // 查询数据
                    var queryData = await db.FmFireclueInfo.AsQueryable()
                        .WhereIF(sourcetype.Count > 0, r => sourcetype.Contains(r.SourceType))
                        .Where(r => r.ReportTime.Year >= startYear && r.ReportTime.Year <= currentYear)
                        .GroupBy(r => r.ReportTime.Year)
                        .Select(r => new
                        {
                            Year = r.ReportTime.Year,
                            TreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State >= 3, 1, 0)),
                            UntreatedCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.State < 3, 1, 0))
                        })
                        .ToListAsync();

                    // 生成结果，确保所有年份都有数据
                    var result = new List<FireInfoStateForChart>();
                    foreach (var year in years)
                    {
                        var yearData = queryData.FirstOrDefault(d => d.Year == year);

                        result.Add(new FireInfoStateForChart
                        {
                            DateTime = year.ToString() + "年",
                            TreatedCount = yearData?.TreatedCount ?? 0,
                            UntreatedCount = yearData?.UntreatedCount ?? 0
                        });
                    }
                    return new Response<List<FireInfoStateForChart>> { Result = result };
                }
            }
        }

        public async Task<Response<List<FireInfoDegreeForChart>>> GetFireClueStatisticsByDegreeType(int type)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                if (type == 1)
                {
                    // 计算14天的日期范围
                    DateTime startDate = DateTime.Now.AddDays(-14).Date;
                    DateTime endDate = DateTime.Now.Date;

                    // 生成14天的日期列表
                    var dateRange = Enumerable.Range(0, (endDate - startDate).Days + 1)
                        .Select(offset => startDate.AddDays(offset))
                        .Select(date => new
                        {
                            Date = date,
                            DayString =date.Month.ToString()+"." +date.Day.ToString()
                        })
                        .ToList();

                    // 查询实际数据
                    var dataQuery = await db.FmFireclueInfo.AsQueryable()
                        .Where(r => r.ReportTime >= startDate && r.ReportTime <= endDate)
                        .GroupBy(r => new { r.ReportTime.Date })
                        .Select(r => new FireInfoDegree
                        {
                            Date = r.ReportTime.Date,
                            ExtraLargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 1, 1, 0)),
                            LargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 2, 1, 0))
                        }).ToListAsync();

                    // 左连接，确保所有日期都显示
                    var list = (from date in dateRange
                                join data in dataQuery on date.Date equals data.Date into gj
                                from subData in gj.DefaultIfEmpty()
                                select new FireInfoDegreeForChart
                                {
                                    DateTime = date.DayString,
                                    ExtraLargeCount = subData?.ExtraLargeCount ?? 0,
                                    LargeCount = subData?.LargeCount ?? 0
                                })
                               .OrderBy(x => x.DateTime)  // 按日期排序
                               .ToList();

                    return new Response<List<FireInfoDegreeForChart>> { Result = list };
                }
                else if (type == 2)
                {
                    // 计算日期范围
                    var now = DateTime.Now;
                    var startDate = new DateTime(now.Year, now.Month, 1).AddMonths(-11);
                    var endDate = new DateTime(now.Year, now.Month, 1).AddMonths(1).AddDays(-1);

                    // 生成月份列表
                    var months = Enumerable.Range(0, 12)
                        .Select(i => new
                        {
                            Year = startDate.AddMonths(i).Year,
                            Month = startDate.AddMonths(i).Month,
                            Display = FormatMonthDisplay(startDate.AddMonths(i))
                        })
                        .ToList();

                    // 查询数据
                    var data = await db.FmFireclueInfo.AsQueryable()
                        .Where(r => r.ReportTime >= startDate && r.ReportTime <= endDate)
                        .GroupBy(r => new { r.ReportTime.Year, r.ReportTime.Month })
                        .Select(r => new
                        {
                            Year = r.ReportTime.Year,
                            Month = r.ReportTime.Month,
                            ExtraLargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 1, 1, 0)),
                            LargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 2, 1, 0))
                        })
                        .ToListAsync();

                    // 使用LINQ左连接
                    var result = (from month in months
                                  join d in data
                                  on new { month.Year, month.Month } equals new { d.Year, d.Month } into gj
                                  from subData in gj.DefaultIfEmpty()
                                  orderby month.Year, month.Month
                                  select new FireInfoDegreeForChart
                                  {
                                      DateTime = month.Display,
                                      ExtraLargeCount = subData?.ExtraLargeCount ?? 0,
                                      LargeCount = subData?.LargeCount ?? 0
                                  }).ToList();
                    return new Response<List<FireInfoDegreeForChart>> { Result = result };
                }
                else
                {
                    // 计算统计年份范围
                    int currentYear = DateTime.Now.Year;
                    int startYear = currentYear - 5 + 1;

                    // 生成年份范围
                    var years = Enumerable.Range(startYear, 5)
                        .Select(y => y)
                        .ToList();

                    // 查询数据
                    var queryData = await db.FmFireclueInfo.AsQueryable()
                        .Where(r => r.ReportTime.Year >= startYear && r.ReportTime.Year <= currentYear)
                        .GroupBy(r => r.ReportTime.Year)
                        .Select(r => new
                        {
                            Year = r.ReportTime.Year,
                            ExtraLargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 1, 1, 0)),
                            LargeCount = SqlFunc.AggregateSum(SqlFunc.IIF(r.DegreeType == 2, 1, 0))
                        })
                        .ToListAsync();

                    // 生成结果，确保所有年份都有数据
                    var result = new List<FireInfoDegreeForChart>();
                    foreach (var year in years)
                    {
                        var yearData = queryData.FirstOrDefault(d => d.Year == year);

                        result.Add(new FireInfoDegreeForChart
                        {
                            DateTime = year.ToString() + "年",
                            ExtraLargeCount = yearData?.ExtraLargeCount ?? 0,
                            LargeCount = yearData?.LargeCount ?? 0
                        });
                    }
                    return new Response<List<FireInfoDegreeForChart>> { Result = result };
                }
            }
        }

        // 格式化月份显示
        private string FormatMonthDisplay(DateTime date)
        {
            var currentYear = DateTime.Now.Year;

            //if (date.Year == currentYear)
            //{
            //    return $"{date.Month}月";
            //}
            //else if (date.Year == currentYear - 1)
            //{
            //    return $"去年{date.Month}月";
            //}
            //else
            //{
            //    return $"{date.Year % 100}年{date.Month}月";
            //}

            return $"{date.Year % 100}.{date.Month}";
        }

        //查询火情和任务列表
        public async Task<Response<List<FmFireclueinfoLog>>> GetFireClueLog(long id)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var list = await db.FmFireclueinfoLog.AsQueryable()
                    .Where(r => r.Fireclueid == id)
                    .OrderByDescending(r => r.CreateTime).ToListAsync();
                return new Response<List<FmFireclueinfoLog>> { Result = list };
            }
        }

        #endregion

        /// <summary>
        /// 在线情况
        /// </summary>
        /// <param name="pageReq"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<dynamic>>> GetPointUserOnLine(UserOnLineReq pageReq)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var user = _auth.GetCurrentUser().User;
                int level = 0;
                //该用户下包含所有部门
                var orgid = _auth.GetCurrentUser().Orgs;
                level = orgid.Min(r => r.Level);
                var chileorglist = new List<long>();
                if (level != 0 && user.Id != -1)
                {
                    foreach (var item in orgid.Where(r => r.Level < 3))
                    {
                        var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, item))
                            .Select(it => it.Id).ToList();
                        chileorglist.AddRange(chileorg);
                    }
                }

                var userInfoQuery = db.User.AsQueryable()
                    .LeftJoin<FmUserPoint>((a, b) => a.Id == b.CreateId)
                    .LeftJoin<SysUserOrg>((a, b, c) => a.Id == c.UserId)
                    .Where((a, b, c) => a.Status == 0)
                    .WhereIF(level != 0, (a, b, c) => chileorglist.Contains(c.UserId));
                var userinfo = await userInfoQuery
                    .Select((a, b, c) => new UserOnLineResp
                    {
                        CreateId = a.Id,
                        Name = a.Name,
                        Lat = b.Lat,
                        Lng = b.Lng,
                        CreateTime = b.CreateTime,
                        Phone = a.Account,
                        State = b.CreateTime.AddMinutes(2) > DateTime.Now ? "在线" : "离线",
                        IsIn = b.Intype,
                        OnLineTime = SqlFunc.DateDiff(DateType.Minute, b.CreateTime, DateTime.Now),
                        TownName = SqlFunc.Subqueryable<SysUserOrg>()
                            .Where(sf => sf.UserId == a.Id)
                            .LeftJoin<SysOrg>((sf, gs) => sf.OrgId == gs.Id)
                            .LeftJoin<SysOrg>((sf, gs, t) => gs.ParentId == t.Id)
                            .SelectStringJoin((sf, gs, t) => gs.Name, ",")
                    })
                    .MergeTable()
                    .Distinct()
                    .WhereIF(!string.IsNullOrEmpty(pageReq.townname), it => it.TownName.Contains(pageReq.townname))
                    .WhereIF(pageReq.isonline != "全部", it => it.State == pageReq.isonline)
                    .OrderByDescending(it => it.CreateTime)
                    .ToPageListAsync(pageReq.page, pageReq.limit, totalNumber);

                var onlineCount = await userInfoQuery
                    .Where((a, b, c) => b.CreateTime.AddMinutes(2) > DateTime.Now)
                    .Select(a => a.Id)
                    .Distinct()
                    .CountAsync();

                // 离线人数
                var offlineCount = totalNumber - onlineCount;

                var enddata = new
                {
                    userinfo,
                    online = onlineCount,
                    offline = offlineCount,
                };


                return new Response<PageInfo<dynamic>>
                {
                    Result = new PageInfo<dynamic> { Items = enddata, Total = totalNumber }
                };
            }
        }

        /// <summary>
        /// 添加实时坐标
        /// </summary>
        /// <param name="userPoint"></param>
        /// <returns></returns>
        public async Task<Response<bool>> AddPointAsync(FmUserPoint userPoint)
        {
            var response = new Response<bool>();
            using var db = Repository.AsSugarClient();

            var currentUser = _auth.GetCurrentUser();
            userPoint.CreateId = currentUser.User.Id;
            userPoint.Id = YitIdHelper.NextId();
            userPoint.CreateTime = DateTime.Now;
            var userPointHistory = userPoint.MapTo<FmUserPointHistory>();

            var oldInfo = await db.Queryable<FmUserPoint>()
                .Where(r => r.CreateId == userPoint.CreateId)
                .FirstAsync();

            //上线弹窗 第一次上报或者上线时间不超过2分钟
            if (oldInfo == null || (oldInfo != null && oldInfo.CreateTime.AddMinutes(2) < DateTime.Now))
            {
                var user = await db.Queryable<SysUser>().Where(r => r.Id == userPoint.CreateId)
                    .FirstAsync();
                if (user != null)
                {
                    await db.Insertable(new FmOnOffLine
                    {
                        Id = YitIdHelper.NextId(),
                        IdentifyId = user.Id.ToString(),
                        OnOffTime = DateTime.Now,
                        Name = user.Name,
                        Type = true
                    }).ExecuteCommandAsync();

                    WebSocketModel wsModel1 = new WebSocketModel
                    {
                        Module = "上线",
                        Data = user.Name
                    };
                    sendsocket(wsModel1);
                }
            }


            if (oldInfo != null)
            {
                oldInfo.Lat = userPoint.Lat;
                oldInfo.Lng = userPoint.Lng;
                oldInfo.CreateTime = userPoint.CreateTime;
                oldInfo.Intype = userPoint.Intype;
                await db.Updateable(oldInfo).ExecuteCommandAsync();
            }
            else
            {
                await db.Insertable(userPoint).ExecuteCommandAsync();
            }

            await db.Insertable(userPointHistory).SplitTable().ExecuteCommandAsync();
            response.Code = 200;
            response.Result = true;
            response.Message = "添加成功";

            return response;
        }

        public async Task sendsocket(WebSocketModel wsModel1)
        {
            try
            {
                if (_socket == null || _socket.State != WebSocketState.Open)
                {
                    string ws = _configuration.GetSection("WebSocket").Value;
                    _socket = new ClientWebSocket();
                    await _socket.ConnectAsync(new Uri(ws), CancellationToken.None);
                }

                byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(wsModel1));
                await _socket.SendAsync(new ArraySegment<byte>(data), WebSocketMessageType.Text,
                    true, CancellationToken.None);
                await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing connection",
                    CancellationToken.None);
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// 保存地图标绘
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        public async Task<Response<bool>> SaveMapPlotting(MapPlottingReq req)
        {
            var record = req.MapTo<FmMapPlotting>();
            record.Id = YitIdHelper.NextId();
            using var db = Repository.AsSugarClient();
            await db.Insertable(record).IgnoreColumnsNull().ExecuteCommandAsync();
            return new Response<bool>()
            {
                Result = true,
                Message = "保存成功",
                Code = 200
            };
        }

        public async Task<Response<PageInfo<dynamic>>> GetMapPlotting(PageReq req)
        {
            using var db = Repository.AsSugarClient();
            RefAsync<int> total = 0;
            var page = await db.Queryable<FmMapPlotting>()
                .OrderByDescending(r => r.CreateTime)
                .ToPageListAsync(req.page, req.limit, total);
            return new Response<PageInfo<dynamic>>
            {
                Code = 200,
                Message = "查询成功",
                Result = new PageInfo<dynamic>
                {
                    Items = page,
                    Total = total
                }
            };
        }

        /// <summary>
        /// 查询人员上报的线索
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByUserId(int pageIndex, int state,
            int pageSize, string userid)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                RefAsync<int> total = 0;
                var list = await db.FmFireclueInfo.AsQueryable().Where(a => a.CreateId.ToString() == userid).Select(a =>
                        new FireClueInfoResp
                        {
                            Id = a.Id,
                            CreateId = a.CreateId.ToString(),
                            ReportPerson = a.ReportPerson,
                            Lat = a.Lat,
                            Lng = a.Lng,
                            Address = a.Address,
                            ReportTime = a.ReportTime,
                            Describe = a.Describe,
                            SourceType = a.SourceType,
                            State = a.State,
                            AreaName = a.AreaName,
                            ClueNo = a.ClueNo,
                        }).Mapper(a => a.SourceTypeName = ((SourceType)a.SourceType).GetDescription())
                    .Mapper(a => a.StateName = ((State)a.State).GetDescription())
                    .OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc).ToPageListAsync(pageIndex, pageSize, total);
                return new Response<PageInfo<List<FireClueInfoResp>>>
                {
                    Code = 200,
                    Message = "查询成功",
                    Result = new PageInfo<List<FireClueInfoResp>>
                    {
                        Items = list,
                        Total = total
                    }
                };
            }
        }

        private static readonly string baseUrl =
            "http://10.176.126.121:8766/liveBroadCast/bd/api/v1/device/liveBroadCast";

        private static readonly string sk = "ba98a152296f13c565d2a6dfd219994f"; // 用户的sk
        private static readonly string account = "AK202006291525121"; // 用户的ak

        public async Task<string> GetFlvUrlAsync(string deviceCode)
        {
            // 获取当前的时间戳
            var requestTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();

            // 构建请求体
            var requestBody = new
            {
                deviceCode = deviceCode
            };

            // 序列化请求体
            var jsonBody = JsonConvert.SerializeObject(requestBody);

            // 计算signature
            var signature = CalculateSignature(requestTime, jsonBody);

            // 创建 HttpClient 和 HttpRequestMessage
            using (var client = new HttpClient())
            {
                // 创建 HttpRequestMessage 实例
                var requestMessage = new HttpRequestMessage(HttpMethod.Post, baseUrl)
                {
                    Content = new StringContent(jsonBody, Encoding.UTF8, "application/json")
                };

                // 设置请求头（其他类型的请求头设置在这里）
                requestMessage.Headers.Add("account", account);
                requestMessage.Headers.Add("requestTime", requestTime);
                requestMessage.Headers.Add("signature", signature);

                // 设置 Content-Type 和 Accept 请求头
                requestMessage.Content.Headers.ContentType =
                    new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                requestMessage.Headers.Accept.Add(
                    new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                // 发送请求
                var response = await client.SendAsync(requestMessage);
                if (response.IsSuccessStatusCode)
                {
                    // 解析响应
                    var responseContent = await response.Content.ReadAsStringAsync();
                    dynamic responseData = JsonConvert.DeserializeObject(responseContent);

                    // 检查返回的code是否为0
                    if (responseData.code == "0")
                    {
                        return responseData.data.flvUrl;
                    }
                    else
                    {
                        throw new Exception($"API error: {responseData.message}");
                    }
                }
                else
                {
                    throw new Exception($"HTTP request failed with status code {response.StatusCode}");
                }
            }
        }

        private string CalculateSignature(string requestTime, string requestBody)
        {
            // 按照要求的计算规则计算signature
            string dataToSign = account + sk + requestTime + requestBody;

            // 使用SHA256算法计算签名
            using (SHA256 sha256 = SHA256.Create())
            {
                byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(dataToSign));
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
            }
        }

        public async Task<string> GetLive(string deviceCode)
        {
            string flvUrl = await GetFlvUrlAsync(deviceCode);
            return flvUrl;
        }

        #region socket

        public async Task SendSocketMessage(WebSocketModel wsModel)
        {
            try
            {
                using (var webSocket = new System.Net.WebSockets.ClientWebSocket())
                {
                    string ws = _configuration.GetSection("WebSocket").Value;
                    await webSocket.ConnectAsync(new Uri(ws), CancellationToken.None);
                    byte[] data = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(wsModel));
                    await webSocket.SendAsync(new ArraySegment<byte>(data),
                        System.Net.WebSockets.WebSocketMessageType.Text, true, CancellationToken.None);
                    await webSocket.CloseAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure,
                        "Closing connection", CancellationToken.None);
                    //webSocket.Dispose();
                }
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// 极光推送
        /// </summary>
        /// <returns></returns>
        public string JPushInfo(string info, long infoid)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                int type = info == "任务下发" ? 2 : 3;
                info = info == "任务下发" ? "有新任务，请注意查收" : "有新火点";
                Audience audience = new Audience();
                if (infoid != 0)
                {
                    var renwu = db.FmFireTaskUser.AsQueryable().Where(r => r.TaskId == infoid).Select(r => r.UserId)
                        .ToList();
                    var users = db.User.AsQueryable().Where(r => renwu.Contains(r.Id.ToString())).ToList();
                    if (users.Count > 0)
                    {
                        audience.Alias = users.Select(a => a.Account).ToList();
                    }
                }
                else
                {
                    var users = db.User.AsQueryable().Where(r => r.UnitName != null).ToList();
                    if (users.Count > 0)
                    {
                        audience.Alias = users.Select(a => a.Account).ToList();
                    }
                }

                PushPayload pushPayload = new PushPayload()
                {
                    Platform = new List<string> { "android", "ios" },
                    Audience = audience,
                    Notification = new Notification
                    {
                        Alert = info,
                        Android = new Android
                        {
                            Alert = info,
                            Title = info,
                            Priority = 2,
                            Extras = new Dictionary<string, object>
                            {
                                ["infoId"] = type,
                                ["type"] = type
                            }
                        }
                    },
                };
                JPushClient client = new JPushClient(_jpoptions.Value.AppKey, _jpoptions.Value.MasterSecret);
                var response = client.SendPush(pushPayload);
                return "success";
            }
        }

        #endregion

        #region 海康设备

        /// <summary>
        /// 获取单个设备的视频流
        /// </summary>
        /// <param name="cameraIndexCode">视频标识</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public string GetPreviewURLs(string cameraIndexCode, string protocol)
        {
            HttpUtillib.SetPlatformInfo(_options.Value.AppKey, _options.Value.SecretKey, _options.Value.Url,
                _options.Value.Port, true);

            var obj = new
            {
                cameraIndexCode,
                streamType = 0,
                protocol = protocol,
                transmode = 1,
                expand = "transcode=0",
                streamform = "ps"
            };
            string body = JsonConvert.SerializeObject(obj);
            string uri = "/artemis/api/video/v2/cameras/previewURLs";
            byte[] result = HttpUtillib.HttpPost(uri, body, 15, 1);
            if (null != result)
            {
                return Encoding.UTF8.GetString(result);
            }

            return "fail";
        }

        /// <summary>
        /// 获取单个设备的视频流---海康平台2
        /// </summary>
        /// <param name="cameraIndexCode">视频标识</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public string GetPreviewURLs2(string cameraIndexCode, string protocol)
        {
            HttpUtillib.SetPlatformInfo(_options2.Value.AppKey, _options2.Value.SecretKey, _options2.Value.Url,
                _options2.Value.Port, true);

            var obj = new
            {
                cameraIndexCode,
                streamType = 0,
                protocol = protocol,
                transmode = 1,
                expand = "transcode=0",
                streamform = "ps"
            };
            string body = JsonConvert.SerializeObject(obj);
            string uri = "/artemis/api/video/v2/cameras/previewURLs";
            byte[] result = HttpUtillib.HttpPost(uri, body, 15, 1);
            if (null != result)
            {
                return Encoding.UTF8.GetString(result);
            }

            return "fail";
        }

        /// <summary>
        /// 获取单个设备的视频流--通用
        /// </summary>
        /// <param name="cameraIndexCode">设备唯一标识吗</param>
        /// <param name="url">设备地址（例：192.168.10.163）</param>
        /// <param name="appkey"></param>
        /// <param name="appsecret"></param>
        /// <param name="port">设备端口（例1443）</param>
        /// <param name="protocol"></param>
        /// <returns></returns>
        public string GetPreviewURL(string cameraIndexCode,string url,string appkey,string appsecret,int port, string protocol)
        {
            HttpUtillib.SetPlatformInfo(appkey, appsecret, url, port, true);

            var obj = new
            {
                cameraIndexCode,
                streamType = 0,
                protocol = protocol,
                transmode = 1,
                expand = "transcode=0",
                streamform = "ps"
            };
            string body = JsonConvert.SerializeObject(obj);
            string uri = "/artemis/api/video/v2/cameras/previewURLs";
            byte[] result = HttpUtillib.HttpPost(uri, body, 15, 1);
            if (null != result)
            {
                return Encoding.UTF8.GetString(result);
            }

            return "fail";
        }


        public async Task<Response<dynamic>> ListCameraWithInRange(string lng, string lat, int radius)
        {
            //  '{lng}', '{lat}' 
            var sql =
                @$"WITH reference_point AS ( SELECT ST_SetSRID ( ST_MakePoint ( '{lng}', '{lat}'  )::geography, 4326 ) AS geom ) SELECT
l.* 
FROM
	fm_camera l,
	reference_point r 
WHERE
	ST_DWithin ( ST_SetSRID ( ST_MakePoint ( l.""Lng"" :: FLOAT, l.""Lat"" :: FLOAT )::geography, 4326 ), r.geom, {radius}
	) 
ORDER BY
	ST_Distance ( ST_SetSRID ( ST_MakePoint ( l.""Lng"" :: FLOAT, l.""Lat"" :: FLOAT )::geography, 4326 ), r.geom ) ";
            var x = await Repository.AsSugarClient().SqlQueryable<dynamic>(sql).ToListAsync();
            return new Response<dynamic>
            {
                Result = x
            };
        }

        public async Task<Response<dynamic>> ListDaHuaCameraInfo(int pageNum, int pageSize, int isOnline)
        {
            var daHuaApi = new DaHuaApi("https://icc-dev.hibetatest.com:4077");
            var channelCategoryRequest = new ChannelCategoryRequest
            {
                pageNum = pageNum,
                pageSize = pageSize,
                isOnline = 1,
                unitTypeList = new List<int> { 1 },
            };
            Console.WriteLine(JsonConvert.SerializeObject(channelCategoryRequest));
            var channelCategoryResponse = await daHuaApi.GetChannelCategoriesAsync(channelCategoryRequest);
            if (channelCategoryResponse.success)
            {
                return new Response<dynamic>
                {
                    Result = channelCategoryResponse.data.pageData
                };
            }

            return new Response<dynamic>
            {
                Code = channelCategoryResponse.code,
                Message = channelCategoryResponse.errMsg
            };
        }

        public async Task<Response<dynamic>> GetDaHuaRtsp(string channelCode, string streamType)
        {
            var daHuaApi = new DaHuaApi("https://icc-dev.hibetatest.com:4077");

            var request = new RtspPreviewRequest
            {
                data = new RtspPreviewData
                {
                    channelId = channelCode,
                    dataType = "1",
                    streamType = streamType //主码流
                }
            };
            var y = await daHuaApi.StartRtspPreviewAsync(request);
            if (y.success)
            {
                return new Response<dynamic>
                {
                    Result = y.data
                };
            }

            return new Response<dynamic>
            {
                Code = y.code,
                Message = y.errMsg
            };
        }
        /// <summary>
        /// 获取设备信息
        /// </summary>
        /// <param name="county"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public TableData LoadCameraInfo(string county, int pageIndex, int pageSize)
        {
            TableData data = new TableData();
            ConnectionConfig connectionConfig = new ConnectionConfig
            {
                ConnectionString = "server=10.176.126.121;Port=33066;Database=inspur_ztk;Uid=lyyj;Pwd=Lyyj1024",
                DbType = DbType.MySql,
                IsAutoCloseConnection = true,
                MoreSettings = new ConnMoreSettings()
                {
                    PgSqlIsAutoToLower = false,//增删查改支持驼峰表 
                }
            };
            using (SqlSugarClient db = new SqlSugarClient(connectionConfig))
            {
                int totalCount = 0;
                var list = db.Queryable<ztk_jcjk_jkdw>()
                    .WhereIF(!string.IsNullOrEmpty(county), r => r.qx.Contains(county))
                    .Select(r => new ztk_jcjk_jkdw()
                    {
                        id = r.id.SelectAll(),
                    })
                    .ToPageList(pageIndex, pageSize, ref totalCount);
                data.data = list;
                data.count = totalCount;
                data.code = 200;
                data.msg = "请求成功";
            }
            return data;
        }



        /// <summary>
        /// 获取应急局摄像头信息---添加到数据库表
        /// </summary>
        /// <param name="county"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<bool>> AddCameraInfoYingJi(string county)
        {
            ConnectionConfig connectionConfig = new ConnectionConfig
            {
                ConnectionString = "server=10.176.126.121;Port=33066;Database=inspur_ztk;Uid=lyyj;Pwd=Lyyj1024",
                DbType = DbType.MySql,
                IsAutoCloseConnection = true,
                MoreSettings = new ConnMoreSettings()
                {
                    PgSqlIsAutoToLower = false,//增删查改支持驼峰表 
                }
            };
            List<FmCamera> fclist=new List<FmCamera>();
            using (SqlSugarClient db = new SqlSugarClient(connectionConfig))
            {
                //var list = db.Queryable<ztk_jcjk_jkdw>()
                //    .WhereIF(!string.IsNullOrEmpty(county), r => r.qx.Contains(county))
                //    .Select(r => new ztk_jcjk_jkdw()
                //    {
                //        id = r.id.SelectAll(),
                //    })
                //    .ToList();
                //foreach(var item in list)
                //{
                //    FmCamera fc=new FmCamera();
                //    fc.Id = Guid.NewGuid().ToString();
                //    fc.Name = item.jkdmckjg+"_热成像";
                //    fc.Model = "ShiYingJiReChengXiang";
                //    fc.Status = item.tyzt; //停用状态
                //    fc.Manufacturer = "大华";
                //    fc.SerialNumber = item.jkdgbidzlkjg;
                //    fc.Ip = "221.2.83.254";
                //    fc.Channel = 0;
                //    fc.Lng = item.jd.ToString();
                //    fc.Lat = item.wd.ToString();
                //    fc.UpdateTime = DateTime.Now;
                //    fc.AppKey = null;
                //    fc.AppSecret = null;
                //    fc.Port = "7012";
                //    fc.RegionPathName = item.ssfz;
                //    fc.CameraType = null;
                //    fc.SerialNumberRcx = item.jkdgbidzlrcx;
                //    fclist.Add(fc);
                //}
            }
            using (var db = base.UnitWork.CreateContext())
            {
                var list = db.FmCamera_yjj.AsQueryable().ToList();
                foreach (var item in list)
                {
                    FmCamera fc = new FmCamera();
                    fc.Id = Guid.NewGuid().ToString();
                    fc.Name = item.jkdmckjg + "_热成像";
                    fc.Model = "ShiYingJiReChengXiang";
                    fc.Status = item.tyzt; //停用状态
                    fc.Manufacturer = "大华";
                    fc.SerialNumber = item.jkdgbidzlkjg;
                    fc.Ip = "221.2.83.254";
                    fc.Channel = 0;
                    fc.Lng = item.jd.ToString();
                    fc.Lat = item.wd.ToString();
                    fc.UpdateTime = DateTime.Now;
                    fc.AppKey = null;
                    fc.AppSecret = null;
                    fc.Port = "7012";
                    fc.RegionPathName = item.ssfz;
                    fc.CameraType = null;
                    fc.SerialNumberRcx = item.jkdgbidzlrcx;
                    fclist.Add(fc);
                }
                var flag= await db.FmCamera.InsertRangeAsync(fclist);
                if (db.Commit()&&flag==true)
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }

        /// <summary>
        /// 海康摄像头添加
        /// </summary>
        /// <param name="ip">海康平台ip</param>
        /// <param name="port">海康平台端口</param>
        /// <param name="pathid">组织架构路径id</param>
        /// <param name="appkey">appkey</param>
        /// <param name="appsecret">appsecret</param>
        /// <returns></returns>
        public async Task<Response<bool>>AddHaiKangCameraInfo(string ip, int port,string pathid,string appkey, string appsecret,int pageno=1,int pagesize=100)
        {
            // 设置平台信息
            HttpUtillib.SetPlatformInfo(appkey, appsecret, ip, port, true);

            // 构建请求参数
            var obj = new
            {
                regionIndexCodes = new string[] { pathid }, // 确保是数组格式
                isSubRegion = true,
                pageNo = pageno,
                pageSize = pagesize,                // 建议不要设置过大，海康可能有最大限制
                orderBy="name",
                orderType= "desc"
            };

            string body = JsonConvert.SerializeObject(obj);
            string uri = "/artemis/api/resource/v2/camera/search";
            byte[] result = HttpUtillib.HttpPost(uri, body, 15,1);
            List<FmCamera> fclist = new List<FmCamera>();
            var param = JsonConvert.DeserializeObject<JObject>(Encoding.UTF8.GetString(result));
            var data= param["data"]["list"];

            using (var db = base.UnitWork.CreateContext())
            {
                foreach (var item in data)
                {
                    //string sql = @"select * from fm_camera1 WHERE ""SerialNumber""='" + item["indexCode"] + "'";
                    //var cam=await Repository.AsSugarClient().SqlQueryable<dynamic>(sql).ToListAsync();
                    //if (cam.Count>0)
                    //{
                        FmCamera fc = new FmCamera();
                        fc.Id = Guid.NewGuid().ToString();
                        fc.Name = item["name"].ToString();
                        var type = item["regionPathName"].ToString();
                        if (type.IndexOf("林场") > -1)
                        {
                            fc.Model = "LinQuSheXiangTou";
                        }
                        else
                        {
                            if (type.IndexOf("林下") > -1)
                            {
                                fc.Model = "ShengTaiLinShiPinJianKong";
                            }
                            else
                            {
                                if (type.IndexOf("高空瞭望") > -1)
                                {
                                    fc.Model = "GaoKongLiaoWang";
                                }
                                else
                                {
                                    fc.Model = "ShiPinJianKong";
                                }
                            }
                        }

                        fc.Status = "0"; //停用状态
                        fc.Manufacturer = "海康";
                        fc.SerialNumber = item["indexCode"].ToString();
                        fc.Ip = ip;
                        fc.Channel = 0;
                        fc.Lng = item["longitude"].ToString();
                        fc.Lat = item["latitude"].ToString();
                        fc.UpdateTime = Convert.ToDateTime(item["createTime"].ToString());
                        fc.AppKey = appkey;
                        fc.AppSecret = appsecret;
                        fc.Port = port.ToString();
                        fc.RegionPathName = item["regionPathName"].ToString();
                        fc.CameraType = Convert.ToInt32(item["cameraType"]);
                        fc.SerialNumberRcx = null;
                        fclist.Add(fc);
                    //}
                    //else
                    //{
                    //    continue;
                    //}

                }
                var flag = await db.FmCamera.InsertRangeAsync(fclist);
                if (db.Commit() && flag == true)
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }


        public async Task<Response<bool>> AddHaiKangCameraInfoBeiFen(string ip, int port, string pathid, string appkey, string appsecret, int pageno = 1, int pagesize = 100)
        {
            // 设置平台信息
            HttpUtillib.SetPlatformInfo(appkey, appsecret, ip, port, true);

            // 构建请求参数
            var obj = new
            {
                regionIndexCodes = new string[] { pathid }, // 确保是数组格式
                isSubRegion = true,
                pageNo = pageno,
                pageSize = pagesize,                // 建议不要设置过大，海康可能有最大限制
                orderBy = "name",
                orderType = "desc"
            };

            string body = JsonConvert.SerializeObject(obj);
            string uri = "/artemis/api/resource/v2/camera/search";
            byte[] result = HttpUtillib.HttpPost(uri, body, 15, 1);
            List<FmCamera> fclist = new List<FmCamera>();
            var param = JsonConvert.DeserializeObject<JObject>(Encoding.UTF8.GetString(result));
            var data = param["data"]["list"];

            using (var db = base.UnitWork.CreateContext())
            {
                foreach (var item in data)
                {
                    string sql = @"select * from fm_camera1 WHERE ""SerialNumber""='" + item["indexCode"] + "'";
                    var cam = await Repository.AsSugarClient().SqlQueryable<dynamic>(sql).ToListAsync();
                    if (cam.Count > 0)
                    {
                        FmCamera fc = new FmCamera();
                        fc.Id = Guid.NewGuid().ToString();
                        fc.Name = item["name"].ToString();
                        var type = item["regionPathName"].ToString();
                        if (type.IndexOf("林场") > -1)
                        {
                            fc.Model = "LinQuSheXiangTou";
                        }
                        else
                        {
                            if (type.IndexOf("生态林") > -1)
                            {
                                fc.Model = "ShengTaiLinShiPinJianKong";
                            }
                            else
                            {
                                if (type.IndexOf("高空瞭望") > -1)
                                {
                                    fc.Model = "GaoKongLiaoWang";
                                }
                                else
                                {
                                    fc.Model = "ShiPinJianKong";
                                }
                            }
                        }

                        fc.Status = "0"; //停用状态
                        fc.Manufacturer = "海康";
                        fc.SerialNumber = item["indexCode"].ToString();
                        fc.Ip = ip;
                        fc.Channel = 0;
                        fc.Lng = item["longitude"].ToString();
                        fc.Lat = item["latitude"].ToString();
                        fc.UpdateTime = Convert.ToDateTime(item["createTime"].ToString());
                        fc.AppKey = appkey;
                        fc.AppSecret = appsecret;
                        fc.Port = port.ToString();
                        fc.RegionPathName = item["regionPathName"].ToString();
                        fc.CameraType = Convert.ToInt32(item["cameraType"]);
                        fc.SerialNumberRcx = null;
                        fclist.Add(fc);
                    }
                    else
                    {
                        continue;
                    }

                }
                var flag = await db.FmCamera.InsertRangeAsync(fclist);
                if (db.Commit() && flag == true)
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }


        /// <summary>
        /// 查询摄像头信息--后台使用
        /// </summary>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FmCamera>>>> GetCameraInfoPageList(FmCameraReq req)
        {
            using (var db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var infos = await db.FmCamera.AsQueryable()
                    .WhereIF(!string.IsNullOrEmpty(req.name), r => r.Name.Contains(req.name))
                    .WhereIF(!string.IsNullOrEmpty(req.model), r => r.Model==req.model)
                    .WhereIF(!string.IsNullOrEmpty(req.manufacturer), r => r.Manufacturer.Contains(req.manufacturer))
                    .WhereIF(!string.IsNullOrEmpty(req.serialnumber), r => r.SerialNumber.Contains(req.serialnumber))
                    .ToPageListAsync(req.page, req.limit, totalNumber);
                return new Response<PageInfo<List<FmCamera>>>
                {
                    Result = new PageInfo<List<FmCamera>> { Items = infos, Total = totalNumber }
                };
            }
        }
        #endregion

        #region 人员类型统计

        /// <summary>
        /// 人员类型统计
        /// </summary>
        /// <returns></returns>
        public async Task<Response<UserTypeStatisticsRes>> GetUserTypeStatistics()
        {
            using var db = Repository.AsSugarClient();
            //护林员
            var hulin = await db.Queryable<SysUserRole>().LeftJoin<SysRole>((s, r) => s.RoleId == r.Id)
                .LeftJoin<SysUser>((s, r, u) => s.UserId == u.Id)
                .Where((s, r, u) => r.Name == "护林员" && u.Id > 0)
                .CountAsync();
            //消防员
            var xiaofang = await db.Queryable<FmFirefighterinfo>().CountAsync();
            //驻防部队
            var zhufang = await db.Queryable<FmZhufangbudui>().CountAsync();
            //林区住户
            var linqu = await db.Queryable<FmLinquzhuhu>().CountAsync();
            //向导
            var xiangdao = await db.Queryable<FmXiangdaouser>().CountAsync();
            //防火驿站
            var yizhan = await db.Queryable<FmFanghuoyizhan>().CountAsync();

            UserTypeStatisticsRes res = new UserTypeStatisticsRes();
            res.hulinyuan = hulin;
            res.xiaofangyuan = xiaofang;
            res.zhufangduiwu = zhufang;
            res.linquzhuhu = linqu;
            res.xiangdao = xiangdao;
            res.fanghuoyizhan = yizhan;

            return new Response<UserTypeStatisticsRes>
            {
                Code = 200,
                Message = "查询成功",
                Result = res
            };
        }

        #endregion

        #region 获取物资相关接口

        /// <summary>
        /// 获取全部营房信息
        /// </summary>
        /// <returns></returns>
        public dynamic GetAllYingFang()
        {
            string sql =
                @"SELECT ""id"",""dwmc"",""dwzd"",""lsdw"",""dwzdjd"",""dwzdwd"",""dzxm"",""lxfs"",""syrs"",""zbqk"",""tbr"", st_astext(""geom"") as geom FROM ""fm_shp_1692148217"" ";

            using (var db = Repository.AsSugarClient())
            {
                var list = db.SqlQueryable<dynamic>(sql).ToList();
                return list;
            }
        }

        /// <summary>
        /// 获取物资储备信息
        /// </summary>
        /// <returns></returns>
        public TableData Loadwuzichubei(string wuzi, string areaname)
        {
            TableData data = new TableData();
            using (var db = Repository.AsSugarClient())
            {
                string sql = string.Empty;
                if (!string.IsNullOrEmpty(wuzi))
                    sql =
                        "SELECT \"id\", \"type\",\"name\",info,st_astext(geom) as geom FROM \"fm_shp_1686205187\"  WHERE info like '%" +
                        wuzi + "%'";
                else
                    sql = "SELECT \"id\", \"type\",\"name\",info,st_astext(geom) as geom FROM \"fm_shp_1686205187\" ";

                var dt = db.Ado.GetDataTable(sql.ToString());
                data.count = dt.Rows.Count;
                data.data = dt;
            }

            return data;
        }

        #endregion

        #region 任务相关

        /// <summary>
        /// 查询我的任务
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FireClueTaskResp>>>> LoadFireClueTaskByUserId(string userid,
            int pageIndex, int pageSize)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmFireclueTask.AsQueryable()
                    .LeftJoin<SysUser>((a, b) => a.TaskUser == b.Id.ToString())
                    .LeftJoin<FmFireTaskUser>((a, b, c) => a.Id == c.TaskId)
                    .Where((a, b, c) => a.IsDelete == false)
                    .Where((a, b, c) => c.UserId == userid)
                    .Select((a, b, c) => new FireClueTaskResp()
                    {
                        Id = a.Id,
                        Content = a.Content,
                        Lat = a.Lat,
                        Lng = a.Lng,
                        Address = a.Address,
                        State = c.State,
                        TaskUserName = b.Name,
                        TaskTime = a.TaskTime,
                        CompleteTime = a.CompleteTime,
                        Audio = a.Audio,
                        Image = a.Image,
                    }).Mapper(c => c.StateName = ((TaskState)c.State).GetDescription())
                    .OrderBy(a => a.TaskTime, OrderByType.Desc)
                    .ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<FireClueTaskResp>>>
                {
                    Result = new PageInfo<List<FireClueTaskResp>> { Items = query, Total = totalNumber }
                };
            }
        }

        /// <summary>
        /// 查询所有任务
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FireClueTaskResp>>>> LoadAllTask(int pageIndex, int pageSize)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmFireclueTask.AsQueryable()
                    .LeftJoin<SysUser>((a, b) => a.TaskUser == b.Id.ToString())
                    .Where((a, b) => a.IsDelete == false)
                    .Select((a, b) => new FireClueTaskResp()
                    {
                        Id = a.Id,
                        Lat = a.Lat,
                        Lng = a.Lng,
                        Address = a.Address,
                        State = a.State,
                        TaskUserName = b.Name,
                        Content = a.Content,
                        Image = a.Image,
                        Audio = a.Audio,
                        TaskTime = a.TaskTime,
                        RecipientUsers = SqlFunc.Subqueryable<FmFireTaskUser>().Where(r => r.TaskId == a.Id)
                            .LeftJoin<SysUser>((r, s) => r.UserId == s.Id.ToString())
                            .SelectStringJoin((a, s) => s.Name, ","),
                    }).Mapper(c => c.StateName = ((TaskState)c.State).GetDescription())
                    .OrderBy(a => a.TaskTime, OrderByType.Desc)
                    .ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<FireClueTaskResp>>>
                {
                    Result = new PageInfo<List<FireClueTaskResp>> { Items = query, Total = totalNumber }
                };
            }
        }

        /// <summary>
        /// 查询火情线索
        /// </summary>
        /// <param name="areaname"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByAreaName(string areaname,
            int pageIndex = 1, int pageSize = 10)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmFireclueInfo.AsQueryable()
                    .WhereIF(!string.IsNullOrEmpty(areaname), (a) => a.AreaName == areaname)
                    .Where(a => a.State == (int)State.上报)
                    .Select((a) => new FireClueInfoResp()
                    {
                        Id = a.Id,
                        CreateId = a.CreateId.ToString(),
                        ReportPerson = a.ReportPerson,
                        Lat = a.Lat,
                        Lng = a.Lng,
                        Address = a.Address,
                        ReportTime = a.ReportTime,
                        Describe = a.Describe,
                        SourceType = a.SourceType,
                        State = a.State,
                        AreaName = a.AreaName,
                        ClueNo = a.ClueNo,
                        Image = a.Image,
                        EventId = a.EventId,
                        Audio = a.Audio,
                        FireType = 1
                    })
                    .Mapper(a => a.SourceTypeName = ((SourceType)a.SourceType).GetDescription())
                    .Mapper(a => a.StateName = ((State)a.State).GetDescription())
                    .OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc)
                    .ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<FireClueInfoResp>>>
                {
                    Result = new PageInfo<List<FireClueInfoResp>> { Items = query, Total = totalNumber }
                };
            }
        }

        /// <summary>
        /// App获取在线人员实时位置信息
        /// </summary>
        /// <param name="areaname"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<List<RYResApp>>> GetPointByAPPAsync()
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmUserPoint.AsQueryable()
                    .LeftJoin<SysUser>((a, b) => a.CreateId == b.Id)
                    .Where((a, b) => a.CreateTime.AddMinutes(2) > DateTime.Now)
                    .Select((a, b) => new RYResApp
                    {
                        CreateId = a.CreateId.ToString(),
                        Name = b.Name,
                        Lat = a.Lat,
                        Lng = a.Lng,
                        CreateTime = a.CreateTime,
                        Type = "人员",
                        Phone = b.Account,
                        top = a.Top,
                        iscontacts = a.IsContacts
                    }).ToListAsync();
                return new Response<List<RYResApp>>
                {
                    Result = query
                };
            }
        }

        #endregion


        #region 感知中心--摄像头类型
        /// <summary>
        /// 感知中心--摄像头类型数量统计
        /// </summary>
        /// <returns></returns>
        public async Task<Response<List<CameraCountRes>>> GetCameraCountByType()
        {
            using (var db = base.UnitWork.CreateContext())
            {
                var typelist = await db.SysDataItemDetail.AsQueryable()
                    .Where(r => r.ItemCode == "FMCamera").ToListAsync();

                var cameralist = await db.FmCamera.AsQueryable().Select(r => new
                {
                    r.Id,
                    r.Name,
                    r.Manufacturer
                }).ToListAsync();

                var camerajj = await db.FmCamera_yjj.AsQueryable().Select<dynamic>(r => new
                {
                    r.id,
                    r.jkdmckjg,
                    r.jklx
                }).ToListAsync();

                List<CameraCountRes> clist = new List<CameraCountRes>();
                foreach (var item in typelist)
                {
                    CameraCountRes cs = new CameraCountRes();
                    cs.title = item.ItemName;
                    if (item.ItemValue == "ShiYingJiReChengXiang")
                    {
                        cs.num = camerajj.Where(r => r.jklx == "森火-市局").Count().ToString();
                    }
                    if (item.ItemValue == "ZhiNengYuYinQiaKou")
                    {
                        cs.num = camerajj.Where(r => r.jklx == "防火卡口").Count().ToString();
                    }
                    if (item.ItemValue == "ShengTaiLinShiPinJianKong")
                    {
                        cs.num = camerajj.Where(r => r.jklx == "森火").Count().ToString();
                    }
                    if (item.ItemValue == "GaoKongLiaoWang")
                    {
                        cs.num = (camerajj.Where(r => r.jklx == "森火").Count() + 2).ToString();
                    }
                    if (item.ItemValue == "ShiPinJianKong")
                    {
                        cs.num = cameralist.Where(r => r.Manufacturer == "海康").Take(458).Count().ToString();
                    }
                    if (item.ItemValue == "LinQuSheXiangTou")
                    {
                        cs.num = cameralist.Where(r => r.Manufacturer == "海康").Take(325).Count().ToString();
                    }
                    if (item.ItemValue == "TieTaJianKong")
                    {
                        cs.num = cameralist.Where(r => r.Manufacturer == "海康").Take(63).Count().ToString();
                    }
                    if (item.ItemValue == "WuRenJiJiChang")
                    {
                        cs.num = "2";
                    }
                    if (item.ItemValue == "FeiXianXianYouJiZhan")
                    {
                        cs.num = cameralist.Where(r => r.Manufacturer == "海康2").Count().ToString();
                    }
                    clist.Add(cs);
                }
                return new Response<List<CameraCountRes>>
                {
                    Result = clist
                };
            }
        }
        #endregion


        #region 在线人员
        public async Task<TableData> GetPointByUserTypeAsync(string unitname, int type)
        {
            TableData data = new TableData();
            using (var db = base.UnitWork.CreateContext())
            {
                if (type == 0)
                {
                    List<RYResApp> reslist = new List<RYResApp>();
                    var info = await db.FmInterphonePoint.AsQueryable()
                        .Where(a => a.time.AddMinutes(20) > DateTime.Now)
                        .Select((a) => new RYResApp
                        {
                            CreateId = a.account,
                            Name = string.IsNullOrEmpty(a.username) ? a.account : a.username,
                            Lat = a.lat.ToString(),
                            Lng = a.lng.ToString(),
                            CreateTime = a.time,
                            Type = "对讲机",
                            Phone = string.IsNullOrEmpty(a.phone) ? a.account : a.phone,
                            top = a.top,
                            UnitName = "",
                            iscontacts = a.iscontacts,
                        }).ToListAsync();

                    var userinfo = await db.FmUserPoint.AsQueryable()
                        .LeftJoin<SysUser>((a, b) => a.CreateId == b.Id)
                        .Where((a, b) => a.CreateTime.AddMinutes(2) > DateTime.Now)
                        .Select((a, b) => new RYResApp
                        {
                            CreateId = a.CreateId.ToString(),
                            Name = b.Name,
                            Lat = a.Lat,
                            Lng = a.Lng,
                            CreateTime = a.CreateTime,
                            Phone = b.Account,
                            Identity = b.Identity,
                            top = a.Top,
                            iscontacts = a.IsContacts,
                            UnitName = b.UnitName == null ? "" : b.UnitName
                        })
                         .Mapper(a => a.Type = ((UserIdentity)a.Identity).GetDescription())
                         .ToListAsync();
                    reslist = info.Union<RYResApp>(userinfo).Where(r => r.Name != null).OrderByDescending(r => r.top).ToList();
                    if (!string.IsNullOrEmpty(unitname))
                    {
                        reslist = reslist.Where(r => r.UnitName == unitname).ToList();
                    }
                    data.data = reslist;
                    data.count = reslist.Count;

                    //查询是否有下线人员
                    List<string> createids = reslist.Select(r => r.CreateId).ToList();
                    var rylist = _cacheContext.Get<List<RYResApp>>("renyuanxinxi");
                    if (rylist != null)
                    {
                        var leave = rylist.Where(r => !createids.Contains(r.CreateId)).Select(r => new
                        {
                            identifyid = r.CreateId,
                            name = r.Name
                        }).ToList();
                        if (leave.Count > 0)
                        {
                            //添加上下线记录
                            List<FmOnOffLine> userlist = new List<FmOnOffLine>();
                            foreach (var item in leave)
                            {
                                var onoff = new FmOnOffLine
                                {
                                    Id = YitIdHelper.NextId(),
                                    IdentifyId = item.identifyid,
                                    OnOffTime = DateTime.Now,
                                    Name = item.name,
                                    Type = false
                                };
                                userlist.Add(onoff);
                            }
                            await db.FmOnOffLine.InsertRangeAsync(userlist);
                            //websocket推送下线消息
                            WebSocketModel wsModel = new WebSocketModel
                            {
                                Module = "下线",
                                Data = leave
                            };
                            //SendWebSocketMessage(wsModel);
                            sendsocket(wsModel);
                        }
                    }
                    _cacheContext.Set("renyuanxinxi", info, DateTime.Now.AddDays(1));

                }
                else if (type == 10)
                {
                    var info = await db.FmInterphonePoint.AsQueryable()
                        .Where(a => a.time.AddMinutes(20) > DateTime.Now)
                        .Select((a) => new RYResApp
                        {
                            CreateId = a.account,
                            Name = string.IsNullOrEmpty(a.username) ? a.account : a.username,
                            Lat = a.lat.ToString(),
                            Lng = a.lng.ToString(),
                            CreateTime = a.time,
                            Type = "对讲机",
                            Phone = string.IsNullOrEmpty(a.phone) ? a.account : a.phone,
                            top = a.top,
                            iscontacts = a.iscontacts,
                        }).ToListAsync();
                    data.data = info;
                    data.count = info.Count;
                }
                else
                {
                    string typename = ((UserIdentity)type).GetDescription();
                    var userinfo = await db.FmUserPoint.AsQueryable()
                        .LeftJoin<SysUser>((a, b) => a.CreateId == b.Id)
                        .Where((a, b) => a.CreateTime.AddMinutes(2) > DateTime.Now)
                        .Where((a, b) => b.Identity == type)
                        .WhereIF(!string.IsNullOrEmpty(unitname), (a, b) => b.UnitName == unitname)
                        .Select((a, b) => new RYResApp
                        {
                            CreateId = a.CreateId.ToString(),
                            Name = b.Name,
                            Lat = a.Lat,
                            Lng = a.Lng,
                            CreateTime = a.CreateTime,
                            Type = typename,
                            Phone = b.Account,
                            top = a.Top,
                            iscontacts = a.IsContacts,
                            UnitName = b.UnitName
                        }).ToListAsync();
                    data.data = userinfo;
                    data.count = userinfo.Count;
                }
            }
            return data;
        }
        #endregion
    }
}