using Hncore.Infrastructure.Common;
using Hncore.Infrastructure.EntitiesExtension;
using Hncore.Infrastructure.Extension;
using Hncore.Infrastructure.WebApi;
using Hncore.Pass.Vpn.Domain;
using Hncore.Pass.Vpn.Model;
using Hncore.Pass.Vpn.Request.Product;
using Hncore.Pass.Vpn.Service;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Hncore.Pass.Vpn.Controllers
{
    [ApiVersion("1.0")]
    [Route("api/course/v{version:apiVersion}/productaccount/[action]")]
    public class ProductAccountController : HncoreControllerBase
    {
        private ProductAccountService m_AccountService;
        private UserService m_UserService;
        private AgentService m_agentService;
        private ProductPackageService m_PackageService;
        private ProductService m_ProductService;
        public ProductAccountController(ProductAccountService _AccountServic
            , UserService _UserService
            , AgentService _agentService
            , ProductPackageService _PackageService
            , ProductService _ProductService)
        {
            m_AccountService = _AccountServic;
            m_UserService = _UserService;
            m_agentService = _agentService;
            m_PackageService = _PackageService;
            m_ProductService = _ProductService;


        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> Post([FromBody]ProductAccountEntity request)
        {
            request.TenantId = this.Request.GetManageUserInfo().TenantId;
            await m_AccountService.Add(request);
            return Success();
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> Put([FromBody]ProductAccountEntity request)
        {
             await m_AccountService.Update(request);
            return Success();
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> Delete([FromQuery]int id)
        {
            var account =  await m_AccountService.Query(m => m.Id == id).FirstOrDefaultAsync();
            account.DeleteTag = 1;

            await m_AccountService.Update(account);
            
            return Success();
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> Deletes([FromBody] List<int> ids)
        {
           var data= m_AccountService.Query(m => ids.Contains(m.Id));
            var flag = await m_AccountService.Deletes(data);
            if (flag)
                return Success();
            else
                return Error("删除失败");
        }


        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> Get([FromQuery]int id)
        {
            var data = await m_AccountService.GetById(id);
            return Success(data);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> Page([FromQuery]AccountPageRequest request)
        {
            Expression<Func<ProductAccountEntity, bool>> expr = m => 1 == 1;
            expr = expr.And(m => m.DeleteTag == 0);
            if (request.UserId > 0)
            {
                expr = expr.And(m => m.UserId == request.UserId);
            }
            if (request.KeyWord.Has())
            {
                expr = expr.And(m => m.UserCode.Contains(request.KeyWord)
                || m.ProductName.Contains(request.KeyWord)
                || m.PackageName.Contains(request.KeyWord)
                || m.Account.Contains(request.KeyWord));
            }
            if (request.ProductIds != null && request.ProductIds.Count > 0)
            {
                expr = expr.And(m =>request.ProductIds.Contains((int)m.ProductId));
            }
            if (request.PackageNames != null && request.PackageNames.Count > 0)
            {
                expr = expr.And(m =>request.PackageNames.Contains((string)m.PackageName));
            }
            if (request.AccountTypes!=null&&request.AccountTypes.Count>0)
            {
                expr = expr.And(m => request.AccountTypes.Contains(m.AccountType));
            }
            if (request.BTime.HasValue && request.ETime.HasValue)
            {
                expr = expr.And(m => m.EndTime>=request.BTime&&m.EndTime<=request.ETime);
            }
            if (request.BkTime.HasValue && request.EkTime.HasValue)
            {
                expr = expr.And(m => m.StartTime>=request.BkTime&&m.StartTime<=request.EkTime);
            }
            if (request.ExpirdDay > -100)
            {
                if (request.ExpirdDay == 0)
                {
                    expr = expr.And(m => m.EndTime.Value < DateTime.Now);
                }else if(request.ExpirdDay == -2){
                    expr = expr.And(m => m.EndTime.Value > DateTime.Now);
                } else if (request.ExpirdDay < 0 && request.ExpirdDay>-4) {
                    expr = expr.And(m => Math.Ceiling((DateTime.Now - m.EndTime).Value.TotalDays) <= Math.Abs(request.ExpirdDay) && m.EndTime < DateTime.Now);
                } else if (request.ExpirdDay==-4) {
                    expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= -4);
                }else if (request.ExpirdDay > 0){
                    expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= request.ExpirdDay && m.EndTime > DateTime.Now);
                }      
                expr = expr.And(m => m.PackageName != "测试卡");     
               // expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) == request.ExpirdDay);
            }
            var ret = await m_AccountService.PageDesc(request.PageIndex, request.PageSize, expr,true,m=>m.Id);
            // ret.List.ForEach(
            //     m => {m.UserCode =  "***";
            // });
            var data = ret.ToApiResult();
            return data;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> Search([FromQuery]AccountPageRequest request)
        {           
            if (request.KeyWord.Has())
            {
                Expression<Func<ProductAccountEntity, bool>> expr = m => (m.Account== request.KeyWord||m.UserCode== request.KeyWord) && m.DeleteTag==0;
                if (request.ProductIds != null && request.ProductIds.Count > 0)
                {
                    expr = expr.And(m =>request.ProductIds.Contains((int)m.ProductId));
                }
                if (request.ExpirdDay > -100)
                {
                    if (request.ExpirdDay == 0)
                    {
                        expr = expr.And(m => m.EndTime.Value < DateTime.Now);
                    }else if(request.ExpirdDay == -2){
                        expr = expr.And(m => m.EndTime.Value > DateTime.Now);
                    } else if (request.ExpirdDay < 0 && request.ExpirdDay>-4) {
                        expr = expr.And(m => Math.Ceiling((DateTime.Now - m.EndTime).Value.TotalDays) <= Math.Abs(request.ExpirdDay) && m.EndTime < DateTime.Now);
                    } else if (request.ExpirdDay==-4) {
                        expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= -4);
                    }else if (request.ExpirdDay > 0){
                        expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= request.ExpirdDay && m.EndTime > DateTime.Now);
                    }      
                    expr = expr.And(m => m.PackageName != "测试卡");     
                // expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) == request.ExpirdDay);
                }
                var ret = await m_AccountService.PageDesc(request.PageIndex, request.PageSize, expr, true, m => m.Id);
                var data = ret.ToApiResult();
                return data;
            }
            return Error("请输入关键字");
        }


        /// <summary>
        /// 迁移
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> BindUser([FromBody]BindUserRequest request)
        {
            var entityList = await m_AccountService.Query(m => request.AccountIds.Contains(m.Id)).ToListAsync();          
            if (entityList == null|| entityList.Count==0)
                return Error("没有选择账号");
            var userEntity= await m_UserService.GetById(request.UserId);
            if (userEntity == null)
                return Error("会员不存在");

            entityList.ForEach(entity =>
            {
                entity.UserId = request.UserId;
                entity.UserCode = userEntity.LoginCode;
                entity.UserPhone = userEntity.Phone;
            });
    
            await m_AccountService.Update(entityList);
            return Success();
        }
        [HttpGet]
        public async Task<ApiResult> GetOrginAccount([FromQuery]string accounts)
        {
            var accountList = await m_AccountService.GetAccounts(string.Join(",", accounts));
            var originModel = await m_agentService.GetOriginAccounts(accountList);
            return Success(originModel);
        }
       

        [HttpGet]
        public async Task<ApiResult> UpdateOrginPwd([FromQuery]int productId, string account, string pwd)
        {
            var flag = await m_agentService.UpdateAccountPwd(productId, account, pwd);
            if (flag)
                return Success();
            else
                return Error("修改密码失败");
        }
        [HttpGet, UserAuth]
        public async Task<ApiResult> ExistAccount([FromQuery]int productId, [FromQuery]string accounts)
        {
            var flag =await m_AccountService.CheckAccountExist(productId, accounts.Split(',').ToList());
            if (flag)
            {
                return Error("账号已经存在");
            }      
            return Success();
        }

        [HttpPost, UserAuth]
        public async Task<ApiResult> CreateTestAccount([FromBody]CreateTestAccountRequest request)
        {
            if (request.Account.NotHas() || request.Pwd.NotHas())
            {
                return Error("账户和密码不能为空");
            }
            if (request.Account == request.Pwd)
            {
                return Error("账户和密码不能一致");
            }
            var userId = this.Request.GetUserInfo().UserId;
            var packageEntity = await m_PackageService.GetById(request.PackageId);
            if (packageEntity==null|| packageEntity.Status==0)
            {
                return Error("套餐不存在");
            }
            if (packageEntity.IsTest == 0&&packageEntity.Id!=1034&&packageEntity.Id!=1040)
            {
                return Error("非测试套餐");
            }

            var flag = await m_AccountService.CheckAccountExist(packageEntity.ProductId, new List<string> { request.Account });
            if (flag)
            {
                return Error("账号已经存在");
            }
            var restTimes = await m_AccountService.GetRestTestCount(userId);        

            var is_verify = await m_AccountService.GetUserStatus(userId);   

            if (restTimes <= 0)
            {
                return Error("没有测试次数了");
            }     

            if (is_verify == 0)
            {
                return Error("请点击前往实名认证");
            }     

            var account_type = 0;
            if (request.PackageId == 1034) {
                account_type = 2;
            } else if (request.PackageId == 1040){
                account_type = 3;
            } else if (request.PackageId == 89){
                account_type = 1;
            } 

            var ret= await m_agentService.NewAccount(0, request.PackageId, request.Account, request.Pwd, accountType:account_type);

            if (ret.Code == ResultCode.C_SUCCESS)
            {         
                var ProductEntity = await m_ProductService.GetById(packageEntity.ProductId);
                var accountEntity = new ProductAccountEntity()
                {
                    Account = request.Account,
                    AccountType = (int)AccountType.Test,
                    ConnectCount = 1,
                    StartTime = DateTime.Now,
                    EndTime = DateTime.Now.AddHours(packageEntity.DayCount),
                    PackageId = packageEntity.Id,
                    PackageName = packageEntity.Name,
                    ProductId = packageEntity.ProductId,
                    ProductName = ProductEntity.Name,
                    Pwd = request.Pwd,
                    ChargeStatus = AccountChargeStatus.Normal,
                    UserId = this.Request.GetUserInfo().UserId,
                    UserCode = this.Request.GetUserInfo().LoginName,
                };
                await m_AccountService.Add(accountEntity);

                var userEntity = await m_UserService.GetById(userId);
                userEntity.UseTestCount++;
                await m_UserService.Update(userEntity);
            }
            return ret;
        }


        //api接口，供新开测试使用
        [HttpPost,AllowAnonymous]
        public async Task<ApiResult> ApiCreateTestAccount([FromBody]CreateTestAccountRequest request)
        {
            if (request.Account.NotHas() || request.Pwd.NotHas())
            {
                return Error("账户和密码不能为空");
            }
            if (request.Account == request.Pwd)
            {
                return Error("账户和密码不能一致");
            }
            if (request.apikey.NotHas())
            {
                return Error("非法请求");
            }
            //通过apikey获取用户信息
            var userEntity = m_UserService.Query(m => m.apikey == request.apikey).FirstOrDefault();
            if (userEntity == null)
            {
                return Error("apikey不正确");
            }
            var userId = userEntity.Id;
            var packageEntity = await m_PackageService.GetById(request.PackageId);
            if (packageEntity==null|| packageEntity.Status==0)
            {
                return Error("套餐不存在");
            }
            if (packageEntity.IsTest == 0&&packageEntity.Id!=1034&&packageEntity.Id!=1040)
            {
                return Error("非测试套餐");
            }

            var flag = await m_AccountService.CheckAccountExist(packageEntity.ProductId, new List<string> { request.Account });
            if (flag)
            {
                return Error("账号已经存在");
            }
            var restTimes = await m_AccountService.GetRestTestCount(userId);        

            var is_verify = await m_AccountService.GetUserStatus(userId);   

            if (restTimes <= 0)
            {
                return Error("没有测试次数了");
            }     

            if (is_verify == 0)
            {
                return Error("请点击前往实名认证");
            }     


            var account_type = 0;
            if (request.PackageId == 1034) {
                account_type = 2;
            } else if (request.PackageId == 1040){
                account_type = 3;
            } else if (request.PackageId == 89){
                account_type = 1;
            } 

            var ret= await m_agentService.NewAccount(0, request.PackageId, request.Account, request.Pwd, accountType:account_type);

            if (ret.Code == ResultCode.C_SUCCESS)
            {         
                var ProductEntity = await m_ProductService.GetById(packageEntity.ProductId);
                var accountEntity = new ProductAccountEntity()
                {
                    Account = request.Account,
                    AccountType = (int)AccountType.Test,
                    ConnectCount = 1,
                    StartTime = DateTime.Now,
                    EndTime = DateTime.Now.AddHours(packageEntity.DayCount),
                    PackageId = packageEntity.Id,
                    PackageName = packageEntity.Name,
                    ProductId = packageEntity.ProductId,
                    ProductName = ProductEntity.Name,
                    Pwd = request.Pwd,
                    ChargeStatus = AccountChargeStatus.Normal,
                    UserId = userEntity.Id,
                    UserCode = userEntity.LoginCode,
                };
                await m_AccountService.Add(accountEntity);

                //前边已经通过apikey获取到数据--故注释
                // var userEntity = await m_UserService.GetById(userId);
                userEntity.UseTestCount++;
                await m_UserService.Update(userEntity);
            }
            return ret;
        }


        /// <summary>
        /// 是否在线
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="account"></param>
        /// <returns></returns>
      // [UserAuth]
      [AllowAnonymous]
        public virtual async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(int productId, string account)
        {
            return await m_agentService.OnLine(productId, account);
        }
        /// <summary>
        /// 踢号
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="account"></param>
        /// <returns></returns>
        // [UserAuth]
        [AllowAnonymous]
        public virtual async Task<ApiResult> KillOut(int productId, string id)
        {
            var status = await m_agentService.KillOut(productId, id);
            if (status) {
                return Success(status);
            } else {
                return Error("");
            }
        }

        [HttpGet]
        public async Task<IActionResult> Export([FromQuery]AccountPageRequest request)
        {

            Expression<Func<ProductAccountEntity, bool>> expr = m => 1 == 1;
            expr = expr.And(m => m.DeleteTag == 0);
            if (request.UserId > 0)
            {
                expr = expr.And(m => m.UserId == request.UserId);
            }
            if (request.KeyWord.Has())
            {
                expr = expr.And(m => m.UserCode.Contains(request.KeyWord)
                || m.ProductName.Contains(request.KeyWord)
                || m.PackageName.Contains(request.KeyWord)
                || m.Account.Contains(request.KeyWord));
            }
            if (request.ProductId != null && request.ProductId > 0)
            {
                expr = expr.And(m =>m.ProductId==request.ProductId);
            }
            if (request.PackageName != null)
            {
                expr = expr.And(m =>request.PackageName==m.PackageName);
            }
            if (request.AccountTypes!=null&&request.AccountTypes.Count>0)
            {
                expr = expr.And(m => request.AccountTypes.Contains(m.AccountType));
            }
            if (request.BTime.HasValue && request.ETime.HasValue)
            {
                expr = expr.And(m => m.EndTime>=request.BTime&&m.EndTime<=request.ETime);
            }
            if (request.BkTime.HasValue && request.EkTime.HasValue)
            {
                expr = expr.And(m => m.StartTime>=request.BkTime&&m.StartTime<=request.EkTime);
            }
            if (request.ExpirdDay > -100)
            {
                if (request.ExpirdDay == 0)
                {
                    expr = expr.And(m => m.EndTime.Value < DateTime.Now);
                }else if(request.ExpirdDay == -2){
                    expr = expr.And(m => m.EndTime.Value > DateTime.Now);
                } else if (request.ExpirdDay < 0 && request.ExpirdDay>-4) {
                    expr = expr.And(m => Math.Ceiling((DateTime.Now - m.EndTime).Value.TotalDays) <= Math.Abs(request.ExpirdDay) && m.EndTime < DateTime.Now);
                } else if (request.ExpirdDay==-4) {
                    expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= -4);
                }else if (request.ExpirdDay > 0){
                    expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) <= request.ExpirdDay && m.EndTime > DateTime.Now);
                }      
                expr = expr.And(m => m.PackageName != "测试卡");     
               // expr = expr.And(m => Math.Ceiling((m.EndTime - DateTime.Now).Value.TotalDays) == request.ExpirdDay);
            }
            var ret = await m_AccountService.PageDesc(request.PageIndex,10000, expr, true, m => m.Id);

            var data = new ExcelData<ProductAccountEntity>
            {
                SheetName = DateTime.Now.ToString("yyyy-MM-dd"),
                Data = ret.List
            };

            var title = new List<ExcelTitle>(){                   
                    new ExcelTitle { Property = "UserCode", Title = "用户" },
                    new ExcelTitle { Property = "ProductName", Title = "产品" },
                    new ExcelTitle { Property = "PackageName", Title = "套餐" },                   
                    new ExcelTitle { Property = "Account", Title = "账号" },
                    new ExcelTitle { Property = "Pwd", Title = "密码" },
                    new ExcelTitle { Property = "AccountType", Title = "类型" , Format=(val)=>((AccountType)val).GetEnumDisplayName() },
                    new ExcelTitle { Property = "ConnectCount", Title = "连接数"},                   
                    new ExcelTitle { Property = "StartTime", Title = "开通时间" , Format=(val)=>((DateTime) val).ToString("yyyy-MM-dd hh:mm:ss")},
                    new ExcelTitle { Property = "EndTime", Title = "到期时间"  ,Format=(val)=>((DateTime) val).ToString("yyyy-MM-dd hh:mm:ss")},
                    new ExcelTitle { Property = "RestTime", Title = "剩余时间" },    
                };
            var fileBytes = ExcelHelper.ExportListToExcel(data, title);

            var fileName = $"{DateTime.Now.ToString("yyyyMMdd")}账号明细.xlsx";
            Response.Headers.Add("X-Suggested-Filename", fileName.UrlEncode());
            return File(fileBytes, "application/octet-stream", fileName);

        }

    }
}
