using OpenAuth.App.BaseApp.Base;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenAuth.App.Interface;
using SqlSugar;
using Infrastructure;
using OpenAuth.App.ServiceApp.Response;
using DocumentFormat.OpenXml.EMMA;
using NPOI.SS.Formula.Functions;
using Infrastructure.Extensions;
using DocumentFormat.OpenXml.Math;
using Microsoft.Extensions.Configuration;
using Infrastructure.CloudSdk.minio;
using Microsoft.AspNetCore.Http;

namespace OpenAuth.App.ServiceApp
{
    public class AirportMaintenanceApp : SqlSugarBaseApp<LasaDronePort, SugarDbContext>
    {
        private readonly IConfiguration _configuration;
        private readonly ISqlSugarClient _client;
        private readonly MinioService _minioService;

        public AirportMaintenanceApp(MinioService minioService, ISqlSugarClient client,
            ISugarUnitOfWork<SugarDbContext> unitWork, IConfiguration configuration,
            ISimpleClient<LasaDronePort> repository, IAuth auth) : base(unitWork, repository, auth)
        {
            _configuration = configuration;
            _client = client;
            _minioService = minioService;
        }

        //获取设备绑定码
        public async Task<Response<LasaDeviceBindingCode>> GetDeviceBindingCode()
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                var info = await db.LasaDeviceBindingCode.AsQueryable().Where(r => r.BindStatus == 0).FirstAsync();

                if (info != null)
                {
                    return new Response<LasaDeviceBindingCode>
                    {
                        Code = 200,
                        Message = "获取设备绑定码成功",
                        Result = info
                    };
                }
                else
                {
                    //如果设备绑定码不存在，则创建一个新的设备绑定码
                    var newBindingCode = new LasaDeviceBindingCode
                    {
                        Id = Guid.NewGuid().ToString(),
                        DeviceBindingCode = Guid.NewGuid().ToString("N").Substring(0, 8), // 生成一个新的绑定码
                        OrgId = "371300", // 默认组织ID
                        OrgName = "临沂市", // 默认组织名称
                        BindStatus = 0 // 未绑定状态
                    };
                    await db.LasaDeviceBindingCode.InsertAsync(newBindingCode);
                    if (db.Commit())
                    {
                        return new Response<LasaDeviceBindingCode>
                        {
                            Code = 200,
                            Message = "获取设备绑定码成功",
                            Result = newBindingCode
                        };
                    }
                    else
                    {
                        return new Response<LasaDeviceBindingCode>
                        {
                            Code = 500,
                            Message = "获取设备绑定码失败",
                        };
                    }
                }
            }
        }

        /// <summary>
        /// 修改注册码状态
        /// </summary>
        /// <param name="DeviceBindingCode"></param>
        /// <returns></returns>
        public async Task<bool> UpdateCodeStatus(string DeviceBindingCode)
        {
            using (var db = UnitWork.CreateContext())
            {
                var flag = await db.LasaDeviceBindingCode.UpdateAsync(it => new LasaDeviceBindingCode()
                {
                    BindStatus = 1,
                }, it => it.DeviceBindingCode == DeviceBindingCode);
                if (db.Commit())
                    return true;
                else
                    return false;
            }
        }

        //使用网关
        public async Task<Response<LasaGateway>> GetGateway()
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                var info = await db.LasaGateway.AsQueryable().Where(r => r.BindStatus == 0).FirstAsync();

                if (info != null)
                {
                    return new Response<LasaGateway>
                    {
                        Code = 200,
                        Message = "获取设备绑定码成功",
                        Result = info
                    };
                }
                else
                {
                    var serverIp = _configuration.GetSection("MQTT:Server").Value;
                    var port = _configuration.GetSection("MQTT:Port").Value;
                    var username = _configuration.GetSection("MQTT:UserName").Value;
                    var password = _configuration.GetSection("MQTT:Password").Value;
                    //如果网关不存在，则创建一个新的
                    var newGateway = new LasaGateway
                    {
                        Id = Guid.NewGuid().ToString(),
                        CreateTime = DateTime.Now,
                        GatewayAccount = username,
                        GatewaySn = Guid.NewGuid().ToString("N").Substring(0, 8).ToUpper(), // 生成一个新的
                        MqttGateway = serverIp + ":" + port,
                        MqttPassword = password,
                        OrgId = "371300", // 默认组织ID
                        BindStatus = 0 // 未绑定状态
                    };
                    await db.LasaGateway.InsertAsync(newGateway);
                    if (db.Commit())
                    {
                        return new Response<LasaGateway>
                        {
                            Code = 200,
                            Message = "获取设备绑定码成功",
                            Result = newGateway
                        };
                    }
                    else
                    {
                        return new Response<LasaGateway>
                        {
                            Code = 500,
                            Message = "获取设备绑定码失败",
                        };
                    }
                }
            }
        }

        public async Task<bool> UpdateGateway(string gateway, string did)
        {
            using (var db = UnitWork.CreateContext())
            {
                var flag = await db.LasaGateway.UpdateAsync(it => new LasaGateway()
                {
                    BindStatus = 1,
                    Did = did,
                    UpdateTime = DateTime.Now,
                }, it => it.GatewaySn == gateway);
                if (db.Commit())
                    return true;
                else
                    return false;
            }
        }
        /// <summary>
        /// 分页获取所有数据 
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<LasaGateway>>>> GetPageList(int page, int limit)
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                var list = await db.LasaGateway.AsQueryable() 
                    .ToPageListAsync(page, limit, totalCount);
                return new Response<PageInfo<List<LasaGateway>>>
                {
                    Result = new PageInfo<List<LasaGateway>> { Items = list, Total = totalCount }
                };
            }
        }
        //获取网关
        public async Task<List<string>> GetGatewaysnList()
        {
            using (var db = UnitWork.CreateContext())
            {
                var info = await db.LasaGateway.AsQueryable().Select(r => r.GatewaySn).ToListAsync();
                if (info != null)
                {
                    return info;
                }
                else
                {
                    return new List<string>();
                }
            }
        }

        public async Task<List<string>> GetUavSn()
        {
            using (var db = UnitWork.CreateContext())
            {
                var uavinfo = await db.LasaUav.AsQueryable().Where(r => r.IsDelete == false).Select(r => r.Sn)
                    .ToListAsync();
                var dockinfo = await db.LasaDronePort.AsQueryable().Where(r => r.IsDelete == false).Select(r => r.Sn)
                    .ToListAsync();

                if (dockinfo != null)
                {
                    return dockinfo.Union(uavinfo).ToList();
                }
                else
                {
                    return new List<string>();
                }
            }
        }

        #region 固件版本管理

        public async Task<Response<bool>> AddFirmware(LasaFirmware info)
        {
            using (var db = UnitWork.CreateContext())
            {
                info.Id = Guid.NewGuid().ToString();
                var flag = await db.LasaFirmware.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>> UpdateFirmware(string id, string version, int type)
        {
            using (var db = UnitWork.CreateContext())
            {
                if (type == 1)
                {
                    var flag = await db.LasaDronePort.UpdateAsync(it => new LasaDronePort()
                    {
                        FirmwareVersion = version,
                    }, it => it.Id == id);
                    if (db.Commit())
                        return new Response<bool> { Result = true, Message = "编辑成功" };
                    else
                        return new Response<bool> { Result = false, Message = "编辑失败" };
                }
                else
                {
                    var flag = await db.LasaUav.UpdateAsync(it => new LasaUav()
                    {
                        FirmwareVersion = version,
                    }, it => it.Id == id);
                    if (db.Commit())
                        return new Response<bool> { Result = true, Message = "编辑成功" };
                    else
                        return new Response<bool> { Result = false, Message = "编辑失败" };
                }
            }
        }

        public Task<string> UploadFile(IFormFile xmlFile)
        {
            return _minioService.UploadFile(xmlFile, "firmware");
        }

        #endregion

        #region 健康报警

        /// <summary>
        /// 添加健康报警
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public bool AddManageDeviceHms(List<LasaManageDeviceHms> newAlarms)
        {
            using (var db = UnitWork.CreateContext())
            {
                var now = DateTime.Now;
                //获取当前所有未处理的告警信息
                var existing = db.LasaManageDeviceHms.AsQueryable()
                    .Where(x => x.IsResolved == 0).ToList();
                var currentKeys = newAlarms.Select(x => x.Code).ToHashSet();
                var existingKeys = existing.Select(x => x.Code).ToHashSet();
                // 需要解除的（老有，新没有） 起的隆冬强
                var toResolve = existing
                    .Where(x => !currentKeys.Contains(x.Code)).ToList();
                foreach (var resolved in toResolve)
                {
                    resolved.IsResolved = 1;
                    resolved.UpdateTime = now;
                }

                db.LasaManageDeviceHms.UpdateRange(toResolve);
                // 需要新增的（新有，老没有）
                var toInsert = newAlarms
                    .Where(x => !existingKeys.Contains(x.Code))
                    .ToList();
                if (toInsert.Count > 0)
                    db.LasaManageDeviceHms.InsertRange(toInsert);
                //var flag = db.LasaManageDeviceHms.InsertRange(newAlarms);
                if (db.Commit())
                    return true;
                else
                    return false;
            }
        }

        //根据时间获取告警信息列表
        public async Task<Response<PageInfo<List<LasaManageDeviceHms>>>> GetManageDeviceHmsList(int level, int model,
            DateTime startTime, DateTime endTime, int page, int limit, string message, string getway)
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                var list = await db.LasaManageDeviceHms.AsQueryable()
                    .Where(x => x.CreateTime >= startTime && x.CreateTime <= endTime)
                    .WhereIF(level != 0, x => x.Level == level)
                    .WhereIF(model != 0, x => x.Module == model)
                    .WhereIF(!string.IsNullOrEmpty(message), x => x.MessageZh.Contains(message))
                    .WhereIF(!string.IsNullOrEmpty(getway), x => x.Sn == getway)
                    .OrderBy(x => x.CreateTime, OrderByType.Desc)
                    .ToPageListAsync(page, limit, totalCount);
                return new Response<PageInfo<List<LasaManageDeviceHms>>>
                {
                    Result = new PageInfo<List<LasaManageDeviceHms>> { Items = list, Total = totalCount }
                };
            }
        }

        #endregion

        #region 日志

        /// <summary>
        /// 添加日志
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public bool AddLog(LasaLog info)
        {
            using (var db = UnitWork.CreateContext())
            {
                var flag = db.LasaLog.Insert(info);
                if (db.Commit())
                    return true;
                else
                    return false;
            }
        }

        /// <summary>
        /// 获取日志
        /// </summary>
        /// <param name="sn"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<LasaLog>>>> GetLogList(string sn, DateTime startTime, DateTime endTime,
            int page, int limit)
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                var topic = $"thing/product/{sn}/osd";
                var list = await db.LasaLog.AsQueryable()
                    .Where(x => x.CreateTime >= startTime && x.CreateTime <= endTime)
                    .Where(x => x.Topic == topic)
                    .OrderBy(x => x.CreateTime, OrderByType.Asc)
                    .ToPageListAsync(page, limit, totalCount);
                return new Response<PageInfo<List<LasaLog>>>
                {
                    Result = new PageInfo<List<LasaLog>> { Items = list, Total = totalCount }
                };
            }
        }

        #endregion

        public async Task<Response<PageInfo<List<LasaMediaFile>>>> GetMediaFile(string taskId, string airId,string device,
           int? type, string picname, DateTime? startTime, DateTime? endTime, int page, int limit, string parentKey,int? objectKeyExist)
        {
            RefAsync<int> totalCount = 0;
            using (var db = UnitWork.CreateContext())
            {
                Console.WriteLine(startTime.ToString());
                var list = await db.LasaMediaFile.AsQueryable()
                    .LeftJoin<LasaTask>((x, b) => x.FlightId == b.FlightId)
                    .WhereIF(!string.IsNullOrEmpty(device), (x, b) => x.DroneModelKey == device)
                    .WhereIF(!string.IsNullOrEmpty(picname), (x, b) => x.Name.Contains(picname))
                    .WhereIF(!string.IsNullOrEmpty(airId), (x, b) => b.AirLineId == airId)
                    .WhereIF(objectKeyExist is 0,(x, b)=> x.ObjectKey  == null)
                    .WhereIF(objectKeyExist is 1,(x, b)=> x.ObjectKey  != null)
                    .WhereIF(!"0001/1/1 0:00:00".Equal(startTime.ToString()), (x, b) => x.CreateTime >= startTime)
                    .WhereIF(!"0001/1/1 0:00:00".Equal(endTime.ToString()), (x, b) => x.CreateTime <= endTime)
                    .WhereIF(!string.IsNullOrEmpty(parentKey), (x, b) => x.ParentKey == parentKey)
                    .WhereIF(!string.IsNullOrEmpty(taskId), (x, b) => x.TaskId == taskId)
                    .WhereIF(type != null, (x, b) => x.Type == type)
                    .OrderBy((x, b) => x.CreateTime, OrderByType.Desc)
                    .Select((x,b) => new LasaMediaFile
                    {
                        Id = x.Id,
                        Name = x.Name,
                        ObjectKey = x.ObjectKey,
                        Path = x.Path,
                        CreateTime = x.CreateTime,
                        TaskId = x.TaskId,
                        Level = x.Level,
                        ParentKey = x.ParentKey,
                        WorkspaceId = x.WorkspaceId,
                        display = x.display,
                        ShowOnMap = x.ShowOnMap,
                        GraffitiJson = x.GraffitiJson,
                        FileTags = x.FileTags,
                        Size = x.Size,
                        Width = x.Width,
                        Height = x.Height,
                        Lat = x.Lat,
                        Lng = x.Lng,
                        AbsoluteAltitude = x.AbsoluteAltitude,
                        Tid = x.Tid,
                        Bid = x.Bid,
                        FlightType = x.FlightType,
                        minipic = x.minipic,
                        CreateUserName = b.CreateUserName,
                        TaskName = b.TaskName,
                        AirLineName = b.TaskAirLineName,
                        GimbalYawDegree = x.GimbalYawDegree,
                        RelativeAltitude = x.RelativeAltitude,
                        PayloadModelName = x.PayloadModelName,
                        Type = x.Type
                    })
                    .ToPageListAsync(page, limit, totalCount);
                return new Response<PageInfo<List<LasaMediaFile>>>
                {
                    Result = new PageInfo<List<LasaMediaFile>> { Items = list, Total = totalCount }
                };
            }
        }


        public async Task<Response<string>> UpdatePicStatus(string id, int showOnMap, int display, string fileTags,
            string graffitiJson)
        {
            string sql = "update lasa_mediafile set \"ShowOnMap\"=" + showOnMap + ",display=" + display +
                         ",\"FileTags\"='" + fileTags + "',\"GraffitiJson\"='" + graffitiJson + "' where \"Id\"='" +
                         id + "'";
            await _client.Ado.ExecuteCommandAsync(sql);
            return new Response<string> { Result = "修改成功!" };
        }

        public async Task<Response<string>> deletepic(string ids)
        {
            string[] idarray = ids.Split(",");

            for (int i = 0; i < idarray.Length; i++)
            {
                string sqlselect = "select \"ObjectKey\" from lasa_mediafile where \"Id\"='" + idarray[i] + "'";
                string objectkey = _client.Ado.SqlQuerySingle<string>(sqlselect);
                string sql = "delete from lasa_mediafile where \"Id\"='" + idarray[i] + "'";
                await _client.Ado.ExecuteCommandAsync(sql);
                await _minioService.DeleteFile(objectkey);
            }

            return new Response<string> { Result = "删除成功!" };
        }


        public async Task<Response<string>> UpdatePicName(string id, string name)
        {
            string sql = "update lasa_mediafile set \"Name\"='" + name + "'  where \"Id\"='" + id + "'";
            await _client.Ado.ExecuteCommandAsync(sql);
            return new Response<string> { Result = "修改成功!" };
        }

        public async Task<Response<string>> UpdatePicParentKey(string id, string ParentKey)
        {
            string sql = "update lasa_mediafile set \"ParentKey\"='" + ParentKey + "'  where \"Id\"='" + id + "'";
            await _client.Ado.ExecuteCommandAsync(sql);
            return new Response<string> { Result = "修改成功!" };
        }
    }
}