using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using OpenAuth.App.BaseApp.Base;
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 SqlSugar;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace OpenAuth.App.ServiceApp.FireManagement
{
    public class FireGridApp : SqlSugarBaseApp<FmCheckInPoint, SugarDbContext>
    {
        public FireGridApp(ISugarUnitOfWork<SugarDbContext> unitWork,
        ISimpleClient<FmCheckInPoint> repository, IAuth auth) : base(unitWork, repository, auth)
        {
            _auth = auth;
        }
        /// <summary>
        /// 添加打卡点
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<Response<bool>> AddCheckPoint(CheckPointReq info)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var checkPoint = info.MapTo<FmCheckInPoint>();
                checkPoint.Id = YitIdHelper.NextId();
                checkPoint.CreateTime = DateTime.Now;
                checkPoint.IsDelete = false;
                List<FmCheckPointUser> sflist = info.UserId
                    .Select(item => new FmCheckPointUser { PointId = checkPoint.Id, UserId = item }).ToList();

                List<FmCheckArea> fck = info.AreaId
                   .Select(item => new FmCheckArea { PointId = checkPoint.Id, AreaId = item }).ToList();

                ////判断是否在巡查范围之内
                //string sqlstr = "SELECT \"Id\" FROM fm_hulinyuanguanhufanwei WHERE ST_Contains(ST_SetSRID(geom, 4326), ST_GeomFromText('POINT(" + info.Lng + " " + info.Lat + ")', 4326)) =TRUE"; ;

                //var dt = await db.Db.Ado.GetDataTableAsync(sqlstr);
                //if (dt.Rows.Count < 1)
                //{
                //    throw new Exception("请在护林员巡查范围内设置打卡点");
                //}
                await db.FmCheckInPoint.InsertAsync(checkPoint);
                await db.FmCheckPointUser.InsertRangeAsync(sflist);
                await db.FmCheckArea.InsertRangeAsync(fck);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }
        //查询打卡点
        public async Task<Response<PageInfo<List<CheckPointInfo>>>> GetCheckPointList(long areaid, string pointName, int pageIndex, int pageSize)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, areaid)).Select(it => it.Id).ToList();

                RefAsync<int> totalNumber = 0;
                var query = await db.FmCheckInPoint.AsQueryable()
                    .LeftJoin<SysUser>((a, b) => a.CreateId == b.Id)
                    .LeftJoin<FmCheckArea>((a, b, c) => a.Id == c.PointId)
                    .Where((a, b) => a.IsDelete == false)
                    .WhereIF(!string.IsNullOrEmpty(pointName), (a, b, c) => a.PointName.Contains(pointName))
                    .WhereIF(areaid != 0, (a, b, c) => chileorg.Contains(c.AreaId))
                    .OrderBy((a,b,c)=>a.PointName)
                    .Select((a, b) => new CheckPointInfo
                    {
                        id = a.Id,
                        pointname = a.PointName,
                        lat = a.Lat,
                        lng = a.Lng,
                        createtime = a.CreateTime,
                        //CreateUserName = b.Name,
                        userinfo = SqlFunc.Subqueryable<FmCheckPointUser>()
                            .Where(c => c.PointId == a.Id)
                            .LeftJoin<SysUser>((c, u) => c.UserId == u.Id)
                            .SelectStringJoin((c, u) => u.Account, ","),
                        userid = SqlFunc.Subqueryable<FmCheckPointUser>()
                            .Where(c => c.PointId == a.Id)
                            .LeftJoin<SysUser>((c, u) => c.UserId == u.Id)
                            .SelectStringJoin((c, u) => u.Id.ToString(), ","),
                    }).ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<CheckPointInfo>>>
                {
                    Result = new PageInfo<List<CheckPointInfo>> { Items = query, Total = totalNumber }
                };
            }
        }
        /// <summary>
        /// 删除打卡点
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Response<bool>> DeleteCheckPoint(long id)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                await db.FmCheckInPoint.UpdateAsync(r => new FmCheckInPoint { IsDelete = true }, r => r.Id == id);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }
            }
        }
        //编辑打卡点
        public async Task<Response<bool>> EditCheckPoint(CheckPointReq info)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                ////判断是否在巡查范围之内
                //string sqlstr = "SELECT \"Id\" FROM fm_hulinyuanguanhufanwei WHERE ST_Contains(ST_SetSRID(geom, 4326), ST_GeomFromText('POINT(" + info.Lng + " " + info.Lat + ")', 4326)) =TRUE"; ;

                //var dt = await db.Db.Ado.GetDataTableAsync(sqlstr);
                //if (dt.Rows.Count < 1)
                //{
                //    throw new Exception("请在护林员巡查范围内设置打卡点");
                //}
                await db.FmCheckInPoint.UpdateAsync(r => new FmCheckInPoint
                {
                    PointName = info.PointName,
                    Lat = info.Lat,
                    Lng = info.Lng
                }, r => r.Id == info.Id);
                //添加人员打卡点中间表
                await db.FmCheckPointUser.DeleteAsync(r => r.PointId == info.Id);
                List<FmCheckPointUser> sflist = info.UserId
                    .Select(item => new FmCheckPointUser { PointId = info.Id, UserId = item }).ToList();
                await db.FmCheckPointUser.InsertRangeAsync(sflist);
                //添加打卡点区域中间表
                await db.FmCheckArea.DeleteAsync(r => r.PointId == info.Id);
                List<FmCheckArea> fck = info.AreaId
                   .Select(item => new FmCheckArea { PointId = info.Id, AreaId = item }).ToList();
                await db.FmCheckArea.InsertRangeAsync(fck);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }

            }
        }
        //获取单条打卡点信息
        public async Task<Response<CheckPointReq>> GetCheckPointById(long id)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var query = await db.FmCheckInPoint.AsQueryable()
                    .Where(a => a.Id == id)
                    .Select(r => new CheckPointReq
                    {
                        Id = r.Id,
                        Lng = r.Lng,
                        Lat = r.Lat,
                        PointName = r.PointName,
                        UserId = SqlFunc.Subqueryable<FmCheckPointUser>().Where(a => a.PointId == id).ToList(a => a.UserId),
                        AreaId = SqlFunc.Subqueryable<FmCheckArea>().Where(a => a.PointId == id).ToList(a => a.AreaId),
                    })
                    .FirstAsync();
                return new Response<CheckPointReq>
                {
                    Result = query
                };
            }
        }


        public async Task<Response<bool>> AddClockOnInfo(FmCheckClockOn info)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                info.Id = YitIdHelper.NextId();
                await db.FmCheckClockOn.InsertAsync(info);
                if (db.Commit())
                {
                    return new Response<bool> { Result = true, Message = "操作成功" };
                }
                else
                {
                    return new Response<bool> { Result = false, Message = "操作失败" };
                }

            }
        }
        /// <summary>
        /// 获取打卡记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<dynamic>>>> GetCheckPointById(long id, int pageIndex = 1, int pageSize = 10)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmCheckClockOn.AsQueryable()
                    .LeftJoin<FmCheckInPoint>((a, b) => a.PointId == b.Id)
                    .LeftJoin<SysUser>((a, b, c) => a.UserId == c.Id)
                    .WhereIF(id != 0, (a, b, c) => a.PointId == id)
                    .Select<dynamic>((a, b, c) => new
                    {
                        a.Id,
                        a.Lng,
                        a.Lat,
                        b.PointName,
                        c.Name,
                        a.UserId
                        //UserId = SqlFunc.Subqueryable<FmCheckPointUser>().Where(a => a.PointId == id).ToList(a => a.UserId),
                        //AreaId = SqlFunc.Subqueryable<FmCheckArea>().Where(a => a.PointId == id).ToList(a => a.AreaId),
                    }).ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<dynamic>>>
                {
                    Result = new PageInfo<List<dynamic>> { Items = query, Total = totalNumber }
                };
            }
        }
        /// <summary>
        /// 获取打卡记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<dynamic>>>> GetCheckInfoByUserId(long id, int pageIndex = 1, int pageSize = 10)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmCheckClockOn.AsQueryable()
                    .LeftJoin<FmCheckInPoint>((a, b) => a.PointId == b.Id)
                    .LeftJoin<SysUser>((a, b, c) => a.UserId == c.Id)
                    .WhereIF(id != 0, (a, b, c) => a.UserId == id)
                    .Select<dynamic>((a, b, c) => new
                    {
                        a.Id,
                        a.Lng,
                        a.Lat,
                        b.PointName,
                        c.Name,
                        a.ClockonTime
                    }).ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<dynamic>>>
                {
                    Result = new PageInfo<List<dynamic>> { Items = query, Total = totalNumber }
                };
            }
        }
        /// <summary>
        /// 查询打卡记录
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="beginTime"></param>
        /// <param name="endTime"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<dynamic>>>> GetClockOnList(long userId, DateTime beginTime, DateTime endTime, int pageIndex, int pageSize)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalNumber = 0;
                var query = await db.FmCheckClockOn.AsQueryable()
                    .LeftJoin<FmCheckInPoint>((a, b) => a.PointId == b.Id)
                    .LeftJoin<SysUser>((a, b, c) => a.UserId == c.Id)
                    .WhereIF(userId != 0, (a, b, c) => a.UserId == userId)
                    .Where((a, b, c) => a.ClockonTime >= beginTime && a.ClockonTime <= endTime)
                    .Select<dynamic>((a, b, c) => new
                    {
                        a.Id,
                        a.ClockonTime,
                        a.Lat,
                        a.Lng,
                        b.PointName,
                        c.Name
                    }).ToPageListAsync(pageIndex, pageSize, totalNumber);
                return new Response<PageInfo<List<dynamic>>>
                {
                    Result = new PageInfo<List<dynamic>> { Items = query, Total = totalNumber }
                };
            }
        }

        public async Task<Response<JObject>> GetStatisticsCount(long areaid, DateTime begintime, DateTime endtime)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var orginfo = await db.SysOrg.AsQueryable().Where(r => r.Id == areaid).FirstAsync();
                var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, areaid)).Select(it => it.Id).ToList();
                JObject obj = new JObject();
                //护林员人数
                var hu = await db.User.AsQueryable().LeftJoin<SysUserRole>((a, b) => a.Id == b.UserId)
                    .LeftJoin<SysUserOrg>((a, b, c) => a.Id == c.UserId)
                    .LeftJoin<SysRole>((a, b, c, d) => b.RoleId == d.Id)
                    .Where((a, b, c, d) => chileorg.Contains(c.OrgId))
                    .Where((a, b, c, d) => d.Name == "护林员").ToListAsync();
                var userId = hu.Select(it => it.Id).Distinct().ToList();
                //巡查距离
                var xunchazongshu = await db.FmUserPointHistory.AsQueryable().Where(a => a.CreateTime >= begintime && a.CreateTime <= endtime && userId.Contains(a.CreateId))
                .SplitTable(begintime, endtime).SumAsync(a => a.Distance);
                //打卡点
                var dakadian = await db.FmCheckInPoint.AsQueryable()
                    .LeftJoin<FmCheckArea>((a, b) => a.Id == b.PointId)
                    .Where((a, b) => a.IsDelete == false && chileorg.Contains(b.AreaId)).CountAsync();
                //打卡次数
                var dakacishu = await db.FmCheckClockOn.AsQueryable()
                    .Where(a => userId.Contains(a.UserId))
                    .Where(a => a.ClockonTime >= begintime && a.ClockonTime <= endtime).CountAsync();
                obj.Add("hulinyuan", userId.Count);
                obj.Add("xunchazongshu", xunchazongshu);
                obj.Add("dakadian", dakadian);
                obj.Add("dakacishu", dakacishu);
                return new Response<JObject>
                {
                    Result = obj
                };
            }
        }
        public async Task<Response<JObject>> GetstatisticsOld(long areaid, DateTime begintime, DateTime endtime, int pageSize, int pageIndex)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var orginfo = await db.SysOrg.AsQueryable().Where(r => r.Id == areaid).FirstAsync();
                var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, areaid)).Select(it => it.Id).ToList();
                var userlist = db.User.AsQueryable().LeftJoin<SysUserRole>((a, b) => a.Id == b.UserId)
                     .LeftJoin<SysUserOrg>((a, b, c) => a.Id == c.UserId)
                     .LeftJoin<SysOrg>((a, b, c, d) => c.OrgId == d.Id)
                     .LeftJoin<SysRole>((a, b, c, d, e) => b.RoleId == e.Id)
                     .Where((a, b, c, d, e) => chileorg.Contains(c.OrgId))
                     .Where((a, b, c, d, e) => e.Name == "护林员")
                     .Select((a, b, c, d, e) => new PointstatisticsResp
                     {
                         Id = a.Id,
                         Name = a.Name,
                         Account = a.Account,
                         AreaName = d.Name,
                         dakacishu = SqlFunc.Subqueryable<FmCheckClockOn>().Where(r => r.UserId == a.Id).Where(r => r.ClockonTime >= begintime && r.ClockonTime <= endtime).Count(),
                         dakadian = SqlFunc.Subqueryable<FmCheckPointUser>().Where(p => p.UserId == a.Id).Count(),
                         lengths = SqlFunc.Subqueryable<FmUserPointHistory>().Where(r => r.CreateId == a.Id).Where(r => r.CreateTime >= begintime && r.CreateTime <= endtime).Sum(r => r.Distance),

                     }).ToList();
                return new Response<JObject>
                {
                    Result = new JObject()
                };
            }
        }
        public async Task<Response<PageInfo<List<PointstatisticsResp>>>> Getstatistics(long areaid, DateTime begintime, DateTime endtime, int pageIndex, int pageSize)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                RefAsync<int> totalPage = 0;
                var orginfo = await db.SysOrg.AsQueryable().Where(r => r.Id == areaid).FirstAsync();
                var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, areaid)).Select(it => it.Id).ToList();
                var userlist = await db.User.AsQueryable().LeftJoin<SysUserRole>((a, b) => a.Id == b.UserId)
                     .LeftJoin<SysUserOrg>((a, b, c) => a.Id == c.UserId)
                     .LeftJoin<SysOrg>((a, b, c, d) => c.OrgId == d.Id)
                     .LeftJoin<SysRole>((a, b, c, d, e) => b.RoleId == e.Id)
                     .Where((a, b, c, d, e) => chileorg.Contains(c.OrgId))
                     .Where((a, b, c, d, e) => e.Name == "护林员")
                     .Select((a, b, c, d, e) => new PointstatisticsResp
                     {
                         Id = a.Id,
                         Name = a.Name,
                         Account = a.Account,
                         AreaName = d.Name,
                     })
                     .ToPageListAsync(pageIndex, pageSize, totalPage);
                foreach (var item in userlist)
                {
                    item.dakacishu = await db.FmCheckClockOn.AsQueryable()
                    .Where(r => r.UserId == item.Id)
                    .Where(r => r.ClockonTime >= begintime && r.ClockonTime <= endtime).CountAsync();
                    item.dakadian = await db.FmCheckPointUser.AsQueryable()
                    .Where(r => r.UserId == item.Id).CountAsync();
                    var lengths = await db.FmUserPointHistory.AsQueryable()
                    .Where(r => r.CreateId == item.Id && r.Intype == 1)
                    .Where(r => r.CreateTime >= begintime && r.CreateTime <= endtime).SplitTable(begintime, endtime).SumAsync(r => r.Distance);

                    item.xunjian = lengths > 0 ? 1 : 0;
                }
                return new Response<PageInfo<List<PointstatisticsResp>>>
                {
                    Result = new PageInfo<List<PointstatisticsResp>> { Items = userlist, Total = totalPage }
                };
            }
        }


        //app根据登录用户获取打卡点
        public async Task<Response<PageInfo<List<dynamic>>>> GetCheckPointByUserId(string userid)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var list = await db.FmCheckPointUser.AsQueryable()
                    .LeftJoin<FmCheckInPoint>((a, b) => a.PointId == b.Id)
                    .Where((a, b) => b.IsDelete == false || b.IsDelete == null)
                    .Select<dynamic>((a, b) => new
                    {
                        id = b.Id,
                        pointname = b.PointName,
                        lat = b.Lat,
                        lng = b.Lng,
                        ischecked = false
                    }).ToListAsync();
                var clockon = await db.FmCheckClockOn.AsQueryable()
                   .Where(r => r.UserId.ToString() == userid)
                   .GroupBy(r => r.PointId)
                   .Select(r => new
                   {
                       pointid = r.PointId,
                       time = SqlFunc.AggregateMax(r.ClockonTime)
                   }).ToListAsync();
                if (clockon.Count > 0)
                {
                    foreach (var item in list)
                    {
                        var data = clockon.Where(r => r.pointid == item.id).ToList();
                        if (data.Count > 0 && (DateTime.Now - data[0].time).Days < 1)
                        {
                            item.ischecked = true;
                        }
                    }
                }
                return new Response<PageInfo<List<dynamic>>>
                {
                    Result = new PageInfo<List<dynamic>> { Items = list, Total = list.Count }
                };
            }


        }

        //导出统计
        //public async MemoryStream ExportStatistics(long areaid, DateTime begintime, DateTime endtime)
        //{
        //    using (SugarDbContext db = base.UnitWork.CreateContext())
        //    {
        //        var orginfo = await db.SysOrg.AsQueryable().Where(r => r.Id == areaid).FirstAsync();
        //        var chileorg = (await db.SysOrg.AsQueryable().ToChildListAsync(it => it.ParentId, areaid)).Select(it => it.Id).ToList();
        //        var userlist = await db.User.AsQueryable().LeftJoin<SysUserRole>((a, b) => a.Id == b.UserId)
        //             .LeftJoin<SysUserOrg>((a, b, c) => a.Id == c.UserId)
        //             .LeftJoin<SysOrg>((a, b, c, d) => c.OrgId == d.Id)
        //             .LeftJoin<SysRole>((a, b, c, d, e) => b.RoleId == e.Id)
        //             .Where((a, b, c, d, e) => chileorg.Contains(c.OrgId))
        //             .Where((a, b, c, d, e) => e.Name == "护林员")
        //             .Select((a, b, c, d, e) => new PointstatisticsResp
        //             {
        //                 Id = a.Id,
        //                 Name = a.Name,
        //                 Account = a.Account,
        //                 AreaName = d.Name,
        //             })
        //             .ToListAsync();
        //        foreach (var item in userlist)
        //        {
        //            item.dakacishu = await db.FmCheckClockOn.AsQueryable()
        //            .Where(r => r.UserId == item.Id)
        //            .Where(r => r.ClockonTime >= begintime && r.ClockonTime <= endtime).CountAsync();
        //            item.dakadian = await db.FmCheckPointUser.AsQueryable()
        //            .Where(r => r.UserId == item.Id).CountAsync();
        //            var lengths = await db.FmUserPointHistory.AsQueryable()
        //            .Where(r => r.CreateId == item.Id && r.Intype == 1)
        //            .Where(r => r.CreateTime >= begintime && r.CreateTime <= endtime).SplitTable(begintime, endtime).SumAsync(r => r.Distance);
        //            item.xunjian = lengths > 0 ? 1 : 0;
        //        }

        //    }

        //}

        //上传坐标
        //public async Task<Response<bool>> UploadLocation(FmUserPoint info)
        //{
        //    using (SugarDbContext db = base.UnitWork.CreateContext())
        //    {
        //        var userPoint = info.MapTo<FmUserPoint>();
        //        checkPoint.Id = YitIdHelper.NextId();
        //        checkPoint.ClockonTime = DateTime.Now;
        //        await db.FmCheckClockOn.InsertAsync(checkPoint);
        //        if (db.Commit())
        //        {
        //            return new Response<bool> { Result = true, Message = "操作成功" };
        //        }
        //        else
        //        {
        //            return new Response<bool> { Result = false, Message = "操作失败" };
        //        }
        //    }
        //}
    }
}
