using Furion.DependencyInjection;
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.BusinessInfo
{
    /// <summary>
    /// 客户管理
    /// </summary>
    public class BusinessService : IBusinessService, ITransient
    {
        private readonly ISqlSugarRepository<YB_Business> repository;
        private readonly SqlSugarClient dbClient;
        private readonly ICommonService _commonService;
        private readonly OperatorModel currentUser;
        public BusinessService(ISqlSugarRepository<YB_Business> sqlSugarRepository, ICommonService commonService)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            _commonService = commonService;
            currentUser = BaseInfoService.GetUserInfo();
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> ChangePasswordAsync(BusienssPwd model)
        {
            var user = await repository.Change<YB_Account>().Context.Queryable<YB_Account>().FirstAsync(x => x.Id == currentUser.UserId);
            if (user == null)
            {
                return new ResultInfo(ResultState.FAIL, "账户未找到");
            }

            var oldpassword = Md5.md5(DESEncrypt.Encrypt(Md5.md5(model.OldPwd, 32).ToLower(), user.Secret).ToLower(), 32).ToLower();
            if (oldpassword != user.Password)
            {
                return new ResultInfo(ResultState.FAIL, "旧密码错误");
            }
            var newpassword = Md5.md5(DESEncrypt.Encrypt(Md5.md5(model.NewPwd, 32).ToLower(), user.Secret).ToLower(), 32).ToLower();
            await dbClient.Updateable<YB_Account>().SetColumns(x => new YB_Account
            {
                Password = newpassword
            }).Where(x => x.Id == user.Id)
            .ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "密码修改成功");
        }
        /// <summary>
        /// 客户详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<BusinessSubmitModel> DetailAsync(int id)
        {
            var buss = await dbClient.Queryable<YB_Business>().FirstAsync(x => x.Id == id);
            var user = await repository.Change<YB_Account>().Context.Queryable<YB_Account>().FirstAsync(x => x.BusinessId == buss.Id);
            return new BusinessSubmitModel
            {
                AccountType = user.AccountType,
                Name = buss.Name,
                Phone = buss.Phone,
                Id = buss.Id,
                Remark = buss.Remark,
                RoleId = user.nRoleId
            };
        }
        /// <summary>
        /// 所有客户列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<YB_Business>> GetAllListAsync(int type = 0)
        {
            var tempquery = dbClient.Queryable<YB_Business>();
            if (type > 0)
            {
                tempquery = tempquery.Where(x => x.Type == type);
            }
            if (currentUser.AccountType != AccountType.platform)
            {
                tempquery = tempquery.Where(x => SqlFunc.StartsWith(x.Code, currentUser.BusinessCode));
            }
            return await tempquery.OrderBy(x => x.CreateTime, OrderByType.Desc).ToListAsync();
        }
        /// <summary>
        /// 客户列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<YB_Business>> GetListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_Business>();
            bool IsAll = false;//是否可查询全部
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(e =>
                {
                    if (!string.IsNullOrEmpty(e.Value))
                    {
                        if (e.Name.ToLower() == "pphone")
                        {
                            temquery = temquery.Where(x => x.Phone == e.Value);
                            IsAll = true;
                        }
                        else
                        {
                            conModels.Add(new ConditionalModel()
                            {
                                FieldName = e.Name,
                                ConditionalType = (ConditionalType)e.Type,
                                FieldValue = e.Value.Trim()
                            });
                        }
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            if (currentUser.AccountType != AccountType.platform & !IsAll)
            {
                temquery = temquery.Where(x => SqlFunc.StartsWith(x.Code, currentUser.BusinessCode) && x.Id != currentUser.BusinessId);
            }
            string sorts = string.Format("{0} {1}", param.sort, param.order);
            var query = await temquery.OrderBy(sorts)
                .Mapper((it, cache) =>
                {
                    if (IsAll)
                    {
                        it.Remark = "***";
                    }
                })
                 .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<YB_Business>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }
        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pwd">密码</param>
        /// <returns></returns>
        public async Task<ResultInfo> ResetPasswordAsync(int id, string pwd)
        {
            if (string.IsNullOrEmpty(pwd))
            {
                pwd = "123456";
            }
            var buss = await dbClient.Queryable<YB_Business>().FirstAsync(x => x.Id == id);
            if (buss == null)
            {
                return new ResultInfo(ResultState.FAIL, "用户未找到");
            }
            var user = await dbClient.Queryable<YB_Account>().FirstAsync(x => x.BusinessId == buss.Id);
            var Password = Md5.md5(DESEncrypt.Encrypt(Md5.md5(pwd, 32).ToLower(), user.Secret).ToLower(), 32).ToLower();
            await dbClient.Updateable<YB_Account>().SetColumns(x => new YB_Account
            {
                Password = Password
            }).Where(x => x.Id == user.Id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "重置成功");
        }
        /// <summary>
        /// 状态变更
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetStatusAsync(int id, StatusType status)
        {
            if (!await dbClient.Queryable<YB_Business>().AnyAsync(x => x.Id == id))
            {
                return new ResultInfo(ResultState.FAIL, "用户未找到");
            }
            await dbClient.Updateable<YB_Business>().SetColumns(x => new YB_Business
            {
                Status = status
            }).Where(x => x.Id == id)
            .EnableDiffLogEvent(new AduitLogS2SDto
            {
                Title = AuditOpConst.UpdateBusinessStatus
            })
            .ExecuteCommandAsync();
            await repository.Change<YB_Account>().Context.Updateable<YB_Account>().SetColumns(x => new YB_Account
            {
                Status = status
            }).Where(x => x.Id == id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "更新成功");
        }
        /// <summary>
        /// 信息提交
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SubmitAsync(BusinessSubmitModel model)
        {
            if (currentUser.AccountType != AccountType.platform)
            {
                model.AccountType = AccountType.agent;
                model.RoleId = Guid.Parse("08D93BAC-E4BB-403E-8DE3-7E9AC647B5F4");
            }
            if (model.Id > 0)
            {
                //检查手机号是否存在
                if (await dbClient.Queryable<YB_Business>().AnyAsync(x => x.Id != model.Id && x.Phone == model.Phone))
                {
                    return new ResultInfo(ResultState.FAIL, "此手机号已注册");
                }
                model.Remark = model.Remark.ToStr();
                await dbClient.Updateable<YB_Business>().SetColumns(x => new YB_Business
                {
                    Name = model.Name,
                    Phone = model.Phone,
                    Remark = model.Remark
                }).Where(x => x.Id == model.Id)
                 .EnableDiffLogEvent(new AduitLogS2SDto
                 {
                     Title = AuditOpConst.UpdateBusiness
                 })
                .ExecuteCommandAsync();

                await dbClient.Updateable<YB_Account>().SetColumns(x => new YB_Account
                {
                    AccountType = model.AccountType,
                    Phone = model.Phone,
                    RealName = model.Name,
                    UserName = model.Phone,
                    nRoleId = model.RoleId
                }).Where(x => x.BusinessId == model.Id).ExecuteCommandAsync();
                return new ResultInfo(ResultState.SUCCESS, "修改成功");
            }
            else
            {
                //检查手机号是否存在
                if (await dbClient.Queryable<YB_Business>().AnyAsync(x => x.Phone == model.Phone))
                {
                    return new ResultInfo(ResultState.FAIL, "此手机号已注册");
                }
                //生成编码
                var code = currentUser.BusinessCode.ToStr();
                string scode = "0001";
                int parentid = currentUser.BusinessId;
                var cnt = await dbClient.Queryable<YB_Business>().CountAsync(x => x.ParentId == currentUser.BusinessId);
                scode = GenCode(cnt);
                if (string.IsNullOrEmpty(scode))
                {
                    return new ResultInfo(ResultState.FAIL, "超过最大注册数量");
                }

                code = $"{code}{scode}";
                var buss = new YB_Business
                {
                    CreateTime = DateTime.Now,
                    Status = StatusType.Enabled,
                    Name = model.Name,
                    Phone = model.Phone,
                    Remark = model.Remark.ToStr(),
                    ParentId = parentid,
                    Type = 1,
                    Code = code
                };
                var bid = await dbClient.Insertable(buss)
                    .EnableDiffLogEvent(new AduitLogS2SDto
                    {
                        Title = AuditOpConst.AddBusienss
                    })
                    .ExecuteReturnIdentityAsync();
                var user = new YB_Account
                {
                    Secret = Md5.md5(Common.CreateNo(), 16).ToLower(),
                    AccountType = model.AccountType,
                    Status = StatusType.Enabled,
                    BusinessId = bid,
                    CreateTime = DateTime.Now,
                    LastVisitIP = "",
                    LastVisitTime = DateTime.Now,
                    Phone = model.Phone,
                    RealName = model.Name,
                    RoleId = 2,
                    nRoleId = model.RoleId,
                    HeadImg = "",
                    UserName = model.Phone
                };
                user.Password = Md5.md5(DESEncrypt.Encrypt(Md5.md5(model.password, 32).ToLower(), user.Secret).ToLower(), 32).ToLower();
                await dbClient.Insertable(user).ExecuteCommandAsync();
                //插入商户数据
                await dbClient.Insertable(new YB_BusinessRealData
                {
                    BusinessCount = 0,
                    CreateTime = DateTime.Now,
                    Balance = 0,
                    BusinessId = bid,
                    DevCount = 0,
                    TodayIncome = 0,
                    TodayResultCnt = 0,
                    TotalIncome = 0,
                    TotalResultCnt = 0,
                    TotalTxAmount = 0,
                    TodayRealCnt = 0,
                    TotalRealCnt = 0,
                    TodayDevCount = 0
                }).ExecuteCommandAsync();
                //更新汇总表
                await _commonService.InsertOrUpdateCombinedAsync();
                return new ResultInfo(ResultState.SUCCESS, "添加成功");
            }
        }
        /// <summary>
        /// 微信登录
        /// </summary>
        /// <param name="openid">用户openid</param>
        /// <returns></returns>
        public async Task<ResultInfo> WXLogin(string openid)
        {
            var wxdata = await dbClient.Queryable<YB_BusinessWX>().FirstAsync(x => x.OpenId == openid);
            if (wxdata == null)
            {
                return new ResultInfo(ResultState.FAIL, "首次扫码请先使用账户密码登录");
            }
            var buss = await dbClient.Queryable<YB_Business>().FirstAsync(x => x.Id == wxdata.BusinessId);
            if (buss == null)
            {
                return new ResultInfo(ResultState.FAIL, "账户未找到");
            }
            var userdata = await dbClient.Queryable<YB_Account>().FirstAsync(x => x.BusinessId == wxdata.BusinessId);
            if (userdata == null)
            {
                return new ResultInfo { code = ResultState.FAIL, message = "账户未找到", data = null };
            }
            if (userdata.Status != StatusType.Enabled)
            {
                return new ResultInfo { code = ResultState.FAIL, message = "账户已禁用" };
            }
            //记录登录信息到cookie和session
            OperatorModel logindata = new OperatorModel
            {
                UserId = userdata.Id,
                RoleId = userdata.nRoleId,
                AccountType = userdata.AccountType,
                BusinessId = userdata.BusinessId,
                BusinessCode = buss != null ? buss.Code : "",
                IsSuper = false,
                LoginIPAddress = Net.Ip,
                LoginTime = DateTime.Now,
                RealName = userdata.RealName,
                Type = buss != null ? buss.Type : 2
            };
            var tokendata = _commonService.AccessToken(logindata);
            return new ResultInfo(ResultState.SUCCESS, "登录成功", tokendata);
        }

        /// <summary>
        /// 生成code
        /// </summary>
        /// <param name="cnt"></param>
        /// <returns></returns>
        private string GenCode(int cnt) =>
            cnt switch
            {
                < 9 => $"000{cnt + 1}",
                < 99 and >= 9 => $"00{cnt + 1}",
                < 999 and >= 99 => $"0{cnt + 1}",
                < 9999 and >= 999 => $"{cnt + 1}",
                _ => ""
            };
    }
}
