using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Mapster;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YBDevice.Core;
using YBDevice.Entity;

namespace YBDevice.Application.OrderInfo
{
    /// <summary>
    /// 订单管理
    /// </summary>
    public class OrderService : IOrderService, ITransient
    {
        private readonly ISqlSugarRepository<YB_Order> repository;
        private readonly SqlSugarClient dbClient;
        private readonly OperatorModel currentUser;
        public OrderService(ISqlSugarRepository<YB_Order> sqlSugarRepository)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            currentUser = BaseInfoService.GetUserInfo();
        }
        /// <summary>
        /// 订单详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<YB_Order> DetailAsync(Guid id)
        {
            return await dbClient.Queryable<YB_Order>().FirstAsync(x => x.Id == id);
        }
        /// <summary>
        /// 订单列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<OrderDto>> GetListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_Order>();
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            if (currentUser.AccountType != AccountType.platform)
            {
                temquery = temquery.Where(x => x.BusinessId == currentUser.BusinessId);
            }
            string sorts = string.Format("{0} {1}", param.sort, param.order);
            var query = await temquery.OrderBy(sorts)
                .Select(x => new OrderList
                {
                    Id = x.Id,
                    Name = x.Name,
                    ShowCount = x.ShowCount,
                    BusinessId = x.BusinessId,
                    CreateTime = x.CreateTime,
                    DayCount = x.DayCount,
                    DayLimit = x.DayLimit,
                    DayRealCount = x.DayRealCount,
                    EndTime = x.EndTime,
                    StartTime = x.StartTime,
                    Priority = x.Priority,
                    RealCount = x.RealCount,
                    Status = x.Status,
                    StatusRemark = x.StatusRemark,
                    TotalCount = x.TotalCount,
                    Type = x.Type,
                    Url = x.Url,
                    OrderType = x.OrderType
                })
                .Mapper((it, cache) =>
                {
                    var alloff = cache.Get(list =>
                    {
                        var ids = list.Where(x => x.Type == OrderType.Office || x.Type == OrderType.Mini).Select(x => x.Url).ToList();
                        return dbClient.Queryable<YB_OfficlaAccount>().Where(x => ids.Contains(x.authorizer_appid)).ToList();
                    });
                    if (it.Type != OrderType.URL)
                    {
                        it.AppName = alloff.FirstOrDefault(x => x.authorizer_appid == it.Url)?.nick_name;
                    }
                    else
                    {
                        it.AppName = it.Url;
                    }
                    var allbuss = cache.Get(list =>
                    {
                        var ids = list.Where(x => x.BusinessId > 0).Select(x => x.BusinessId).ToList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.BusinessName = allbuss.FirstOrDefault(x => x.Id == it.BusinessId)?.Name;
                })
                 .ToPageListAsync(param.offset, param.limit, totalnum);
            var list = query.Adapt<List<OrderDto>>();
            return new PageParms<OrderDto>
            {
                page = param.offset,
                Items = list,
                totalnum = totalnum,
                limit = param.limit
            };
        }
        /// <summary>
        /// 获取订单设备列表
        /// </summary>
        /// <param name="orderid"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <param name="code">设备序列号</param>
        ///  <param name="type">设备类型</param>
        /// <returns></returns>
        public async Task<PageParms<OrderEquDto>> GetOrderEquListAsync(Guid orderid, int page = 1, int pagesize = 50, string code = "", int type = 0)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = dbClient.Queryable<YB_Device>();
            if (currentUser.AccountType != AccountType.platform)
            {
                tempquery = tempquery.Where(x => x.BusinessId == currentUser.BusinessId || x.BindBusinessId == currentUser.BusinessId);
            }
            if (!string.IsNullOrEmpty(code))
            {
                tempquery = tempquery.Where(x => x.FacCode.Contains(code));
            }
            if (type > 0)
            {
                tempquery = tempquery.Where(x => x.Type == type);
            }
            List<YB_OrderEqu> bindlist = new List<YB_OrderEqu>();
            if (orderid != Guid.Empty)
            {
                bindlist = await dbClient.Queryable<YB_OrderEqu>().Where(x => x.OrderId == orderid).ToListAsync();
                if (bindlist.Count == 1 && bindlist.FirstOrDefault().EquId == 0)
                {
                    var order = await dbClient.Queryable<YB_Order>().Where(x => x.Id == orderid).Select(x => new YB_Order
                    {
                        BusinessId = x.BusinessId
                    }).FirstAsync();
                    bindlist = await tempquery.Clone().Where(x => x.BusinessId == order.BusinessId || x.BindBusinessId == order.BusinessId).Select(x => new YB_OrderEqu
                    {
                        EquId = x.Id
                    }).ToListAsync();
                }
            }

            var query = await tempquery.Clone().OrderBy(x => x.CreateTime, OrderByType.Desc)
                .Select(x => new OrderEquDto
                {
                    equid = x.Id,
                    facecode = x.FacCode,
                    name = x.Name
                })
                .Mapper((it, cache) =>
                {
                    if (bindlist != null && bindlist.Count == 1 && bindlist.FirstOrDefault().EquId == 0)
                    {
                        it.isall = true;
                    }
                    if (bindlist == null || bindlist.Count == 0)
                    {
                        it.ischecked = false;
                    }
                    if (
                    (bindlist != null && bindlist.Count == 1 && bindlist.FirstOrDefault().EquId == 0)
                    || (bindlist != null && bindlist.Any(x => x.EquId == it.equid))
                    )
                    {
                        it.ischecked = true;
                    }
                })
                .ToPageListAsync(page, pagesize, totalnum);
            return new PageParms<OrderEquDto>
            {
                page = page,
                Items = query,
                totalnum = totalnum,
                limit = pagesize
            };
        }

        /// <summary>
        /// 状态变更
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetStatusAsync(Guid id, OrderStatus status)
        {
            if (!await dbClient.Queryable<YB_Order>().AnyAsync(x => x.Id == id))
            {
                return new ResultInfo(ResultState.FAIL, "订单未找到");
            }
            string statusremark = "";
            if (status == OrderStatus.Pause)
            {
                statusremark = currentUser.AccountType != AccountType.platform ? "用户暂停" : "系统暂停";
            }
            await dbClient.Updateable<YB_Order>().SetColumns(x => new YB_Order
            {
                Status = status,
                StatusRemark = statusremark
            }).Where(x => x.Id == id)
             .EnableDiffLogEvent(new AduitLogS2SDto
             {
                 Title = AuditOpConst.UpdateOrderStatus
             })
            .ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "状态更新成功");
        }
        /// <summary>
        /// 信息提交
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SubmitAsync(OrderSubmitDto model)
        {
            if (model.Type == OrderType.URL && (string.IsNullOrEmpty(model.Url) || !model.Url.ToLower().StartsWith("http")))
            {
                return new ResultInfo(ResultState.FAIL, "链接地址格式不正确");
            }
            if (model.Type == OrderType.Office && string.IsNullOrEmpty(model.Url))
            {
                return new ResultInfo(ResultState.FAIL, "请先选择公众号");
            }
            if (model.Type == OrderType.Mini && string.IsNullOrEmpty(model.Url))
            {
                return new ResultInfo(ResultState.FAIL, "请先选择小程序");
            }
            //如果是用户测量场景则只能使用授权的小程序
            if (model.OrderType == OrderBindType.UserMea && await dbClient.Queryable<YB_OfficlaAccount>().AnyAsync(x => x.authorizer_appid == model.Url && x.type == 2 && x.service_type_info == "小程序"))
            {
                return new ResultInfo(ResultState.FAIL, "用户测量场景只支持授权的小程序");
            }
            model.Page = model.Page.ToStr();
            if (model.Id != Guid.Empty)
            {
                await dbClient.Updateable<YB_Order>().SetColumns(x => new YB_Order
                {
                    Name = model.Name,
                    StartTime = model.StartTime,
                    EndTime = model.EndTime,
                    DayLimit = model.DayLimit,
                    Priority = model.Priority,
                    TotalCount = model.TotalCount,
                    Type = model.Type,
                    Url = model.Url,
                    Page = model.Page,
                    OrderType = model.OrderType
                }).Where(x => x.Id == model.Id)
                .EnableDiffLogEvent(new AduitLogS2SDto
                {
                    Title = AuditOpConst.UpdateOrder
                })
                .ExecuteCommandAsync();
                await dbClient.Deleteable<YB_OrderEqu>().Where(x => x.OrderId == model.Id).ExecuteCommandAsync();
                if (model.equids != null && model.equids.Count > 0)
                {
                    List<YB_OrderEqu> list = new List<YB_OrderEqu>();
                    foreach (var item in model.equids)
                    {
                        list.Add(new YB_OrderEqu
                        {
                            EquId = item,
                            OrderId = model.Id
                        });
                    }
                    await dbClient.Insertable(list).ExecuteCommandAsync();
                }
                return new ResultInfo(ResultState.SUCCESS, "订单修改成功");
            }
            else
            {
                var order = new YB_Order
                {
                    Id = IDGen.NextID(),
                    CreateTime = DateTime.Now,
                    StartTime = model.StartTime,
                    EndTime = model.EndTime,
                    Status = OrderStatus.Pause,
                    RealCount = 0,
                    ShowCount = 0,
                    DayCount = 0,
                    DayRealCount = 0,
                    StatusRemark = "",
                    BusinessId = currentUser.BusinessId,
                    DayLimit = model.DayLimit,
                    Name = model.Name,
                    Priority = model.Priority,
                    TotalCount = model.TotalCount,
                    Type = model.Type,
                    Url = model.Url,
                    Page = model.Page,
                    OrderType = model.OrderType
                };
                await dbClient.Insertable(order).ExecuteCommandAsync();
                if (model.equids != null && model.equids.Count > 0)
                {
                    List<YB_OrderEqu> list = new List<YB_OrderEqu>();
                    foreach (var item in model.equids)
                    {
                        list.Add(new YB_OrderEqu
                        {
                            EquId = item,
                            OrderId = order.Id
                        });
                    }
                    await dbClient.Insertable(list)
                        .ExecuteCommandAsync();
                }
                return new ResultInfo(ResultState.SUCCESS, "订单创建成功");
            }
        }
    }
}
