package fronted

import (
	"errors"
	"fmt"
	"go-admin/app/admin/models"
	"go-admin/app/admin/models/sysmodel"
	"go-admin/app/admin/service"
	"go-admin/app/admin/service/aduserdb"
	"go-admin/app/admin/service/appservice"
	"go-admin/app/admin/service/common"
	"go-admin/app/admin/service/dto"
	"go-admin/common/global"
	"go-admin/common/service/sysservice/authservice"
	"go-admin/common/service/sysservice/sysstatuscode"
	statuscode "go-admin/common/status_code"
	ext "go-admin/config"
	"go-admin/models/coingatedto"
	"go-admin/pkg/cryptohelper/inttostring"
	"go-admin/pkg/utility"
	"go-admin/services/cacheservice"
	"go-admin/services/udunservice"

	"github.com/bytedance/sonic"
	"github.com/gin-gonic/gin"
	"github.com/go-admin-team/go-admin-core/logger"
	"github.com/go-admin-team/go-admin-core/sdk/api"
	"gorm.io/gorm"
)

type LineUserApi struct {
	api.Api
}

// Register 用户注册
func (e LineUserApi) Register(c *gin.Context) {
	s := service.LineUser{}
	userAppService := appservice.LineUser{}
	balanceService := service.MemberBalance{}
	req := sysmodel.FrontedUserRegisterReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		MakeService(&userAppService.Service).
		MakeService(&balanceService.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	//校验参数
	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	// 注册前校验
	pid, code := authservice.UserRegisterBefore(e.Orm, req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	req.Pid = pid
	req.IP = utility.GetIp(c)
	ok, user := authservice.UserRegister(e.Orm, req)
	if ok != statuscode.OK {
		e.Error(ok, nil, sysstatuscode.GetStatusCodeDescription(c, ok))
		return
	}

	userAppService.SetDefaultRenwal(user)
	balanceService.CreateDefaultBalance(user)

	resp := map[string]interface{}{
		"email":      req.Email,
		"mobile":     req.Phone,
		"status":     "verify",
		"login_type": 2,
		"jwt_token":  "",
		"jwt_expire": "",
	}
	if req.RegisterType == sysmodel.TSmsCode {
		if req.Pid > 0 {
			updateSql := `UPDATE line_user SET recommend_num = recommend_num + 1 WHERE id = ?`
			if err := e.Orm.Exec(updateSql, req.Pid).Error; err != nil {
				e.Logger.Error(err)
			}
		}
		token, expire, _ := authservice.GenerateToken(user.Id, 1, user.Mobile, user.Mobile, user.Email, req.IP, "PC")
		resp["jwt_token"] = token
		resp["jwt_expire"] = expire
		resp["status"] = "normal"
	}

	e.OK(resp, "success")
}

// VerifyEmail 验证邮箱
func (e LineUserApi) VerifyEmail(c *gin.Context) {
	s := service.LineUser{}
	req := dto.FrontedUserVerifyEmailReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	if req.VerifyCode == "" || req.Email == "" {
		e.Error(statuscode.ParameterInvalid, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ParameterInvalid))
		return
	}
	// 核验邮箱验证码
	code := authservice.UserVerifyEmail(req.Email, req.VerifyCode, 0, e.Orm)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	ok := s.UserVerifyEmail(req.Email)
	if ok != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")

}

// SendVerifyEmail 发送邮箱
func (e LineUserApi) SendVerifyEmail(c *gin.Context) {
	s := service.LineUser{}
	req := dto.FrontedSendVerifyEmailReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	emailCode := inttostring.GenerateRandomString(10)
	language := common.GetLanguage(c)
	code = authservice.SendRegisterEmail(req.Email, emailCode, req.Type, language)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")

}

// SendRegisterSms 发送注册短信
func (e LineUserApi) SendRegisterSms(c *gin.Context) {
	s := service.LineUser{}
	req := dto.FrontedSendVerifySmsReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	if req.Type == 0 {
		user, _ := aduserdb.GetUserByPhone(e.Orm, req.PhoneAreaCode, req.Phone)
		if user.Id > 0 {
			e.Error(statuscode.TheAccountIsAlreadyRegistered, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.TheAccountIsAlreadyRegistered))
			return
		}
	}

	code = authservice.SendGoToneSms(req.Phone, req.PhoneAreaCode, req.Type)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")

}

// Login 登录
func (e LineUserApi) Login(c *gin.Context) {
	s := service.LineUser{}
	req := dto.FrontedLoginReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	// 登录前校验
	user, code, langArg := authservice.UserPwdLoginBefore(e.Orm, req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDiscreptionArgs(c, code, langArg))
		return
	}
	token, expire, code := authservice.GenerateToken(user.Id, 1, user.Email, user.Mobile, user.Email, utility.GetIp(c), "PC")
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
		// return app.Fail(ctx, code)
	}
	resp := map[string]interface{}{
		"email":      req.Email,
		"mobile":     "",
		"status":     user.Status,
		"login_type": 2,
		"jwt_token":  token,
		"jwt_expire": expire,
	}
	e.OK(resp, "success")

}

func (e LineUserApi) UserInfo(c *gin.Context) {
	userId := common.GetUserId(c)
	var user models.LineUser
	err := e.Orm.Model(&models.LineUser{}).Where("id = ?", userId).Find(&user).Error
	if err != nil && !errors.Is(err, gorm.ErrNotImplemented) {
		e.Error(statuscode.UserIdInvalid, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.UserIdInvalid))
		return
	}

	if user.Status == "verify" {
		e.Error(statuscode.UserNotVerify, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.UserNotVerify))
		return
	}

	e.OK(nil, "success")
}

// AddApiKey 用户手动添加apikey
func (e LineUserApi) AddApiKey(c *gin.Context) {
	s := service.LineUser{}
	req := dto.AddApiKeyReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	code = s.AddApiKey(common.GetUserId(c), &req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")
}

// UpdateApiKey 修改apikey
func (e LineUserApi) UpdateApiKey(c *gin.Context) {
	s := service.LineUser{}
	req := dto.AddApiKeyReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	code := req.CheckParams()
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	code = s.UpdateApiKey(common.GetUserId(c), &req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")

}

// GetWhiteIp 用户手动获取ip
func (e LineUserApi) GetWhiteIp(c *gin.Context) {
	//s := service.LineUser{}
	configS := service.SysConfig{}
	//req := dto.AddApiKeyReq{}
	err := e.MakeContext(c).
		MakeOrm().
		MakeService(&configS.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	req := dto.SysConfigByKeyReq{ConfigKey: "sys_user_white_ip"}
	var resp dto.GetSysConfigByKEYForServiceResp
	err = configS.GetWithKey(&req, &resp)
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	e.OK(resp.ConfigValue, "success")

}

// Info 用户中心
func (e LineUserApi) Info(c *gin.Context) {
	s := service.LineUser{}
	balance := service.MemberBalance{}
	err := e.MakeContext(c).
		MakeOrm().
		MakeService(&s.Service).
		MakeService(&balance.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	userId := common.GetUserId(c)
	binanceAccount := service.BinanceAccount{Service: s.Service}

	//获取用户资金账户资产
	totalAsset, err := binanceAccount.GetTotalAsset(userId)

	if err != nil {
		e.Logger.Errorf("获取用户资金账户资产失败:%v", err)
	}
	resp, err := binanceAccount.GetFundingAsset(userId)
	if err != nil {
		e.Logger.Error(500, err, err.Error())
		return
	}

	tickerData, _ := cacheservice.GetExchangeTradeSets(global.EXCHANGE_BINANCE, 1)
	for i, asset := range resp {
		symbol := asset.Asset + "USDT"
		for _, datum := range tickerData {
			if datum.Symbol == symbol {
				// mul := utility.StringToDecimal(datum.Price).Mul(utility.StringToDecimal(asset.Free))
				// usdtBalance = usdtBalance.Add(mul)
				resp[i].UsdtValuation = datum.LastPrice
			}
		}
	}

	// 邀请人数
	var inviteNum int64
	var userinfo models.LineUser
	e.Orm.Model(&models.LineUser{}).Where("id = ?", userId).Find(&userinfo)
	e.Orm.Model(&models.LineUser{}).Where("pid =? or top_referrer_id =?", userId, userId).Count(&inviteNum)

	var apiUserinfo models.LineApiUser
	e.Orm.Model(&models.LineApiUser{}).Where("user_id = ? ", userId).Find(&apiUserinfo)
	var isAuth bool
	if apiUserinfo.ApiKey != "" && apiUserinfo.ApiSecret != "" {
		isAuth = true
	}
	//持仓分布
	var fundingAsset []models.FundingAsset
	if len(resp) > 10 {
		fundingAsset = resp[0:10]
	} else {
		fundingAsset = resp[0:]
	}

	balanceData, _ := balance.GetBalance(userId)

	//获取盈利情况
	logs := service.LineUserProfitLogs{Service: s.Service}
	totalProfit, todayProfit := logs.GetProfitInfoByUserId(userinfo.Id)
	user := map[string]interface{}{
		"avatar":      userinfo.Avatar,
		"user_id":     userinfo.Id,
		"user_name":   userinfo.Nickname,
		"invite_num":  inviteNum,
		"open_status": apiUserinfo.OpenStatus,
		"is_auth":     isAuth,
		"invite_url":  fmt.Sprintf("%s/invice_url?invite_code=%s", ext.ExtConfig.Domain, userinfo.InviteCode),
		"invite_code": userinfo.InviteCode,
		"api_name":    apiUserinfo.ApiName,
		"api_key":     inttostring.EncryptString(apiUserinfo.ApiKey, 4, 4),
		"api_secret":  inttostring.EncryptString(apiUserinfo.ApiSecret, 4, 4),
	}
	returnMap := map[string]interface{}{
		"u_balance":     totalAsset.Truncate(2),
		"margin":        userinfo.Money,
		"userinfo":      user,
		"funding_asset": fundingAsset,
		"total_profit":  totalProfit.Float64,
		"today_profit":  todayProfit.Float64,
		"balance": map[string]interface{}{ //系统余额
			"total_amount":  balanceData.TotalAmount,
			"free_amount":   balanceData.FreeAmount,
			"frozen_amount": balanceData.FrozenAmount,
		},
	}
	e.OK(returnMap, "success")

}

// OpenStatus 开启或者关闭
func (e LineUserApi) OpenStatus(c *gin.Context) {
	s := service.LineUser{}
	req := dto.OpenStatusReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	userId := common.GetUserId(c)
	code := s.OpenStatus(&req, userId)

	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(nil, "success")
}

// RechargeNetworkList 充值 通过充值币种选择主网络
func (e LineUserApi) RechargeNetworkList(c *gin.Context) {
	s := service.LineUser{}
	req := dto.RechargeListReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	data, code := s.RechargeNetworkList(&req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(data, "success")
}

// RechargeNetworkAddress 充值 通过主网ID和用户ID获取交易地址
func (e LineUserApi) RechargeNetworkAddress(c *gin.Context) {
	s := service.LineUser{}
	req := dto.RechargeAddressListReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	req.UserId = common.GetUserId(c)
	data, code := s.RechargeNetworkAddress(&req)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(data, "success")
}

// Notify uDun回调
func (e LineUserApi) Notify(c *gin.Context) {
	timestamp := c.PostForm("timestamp")
	nonce := c.PostForm("nonce")
	body := c.PostForm("body")
	sign := c.PostForm("sign")
	callback := udunservice.TradeCallback(e.Orm, timestamp, nonce, body, sign)
	c.String(200, callback)
	//c.Writer.WriteString(callback)
	return
}

// FundingTrend 资金走势
func (e LineUserApi) FundingTrend(c *gin.Context) {
	s := service.LineUser{}
	req := dto.RechargeAddressListReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	userId := common.GetUserId(c)
	data, code := s.FundingTrend(userId)
	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}
	e.OK(data, "success")
}

// PreOrder 预下单
func (e LineUserApi) PreOrder(c *gin.Context) {
	s := service.LineUser{}
	req := dto.VtsRechargePreOrderReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	userId := common.GetUserId(c)
	resp := dto.VtsRechargePreOrderResp{}
	err = s.PreOrder(userId, &req, &resp)
	if err != nil {
		e.Error(500, err, fmt.Sprintf("发起充值失败,\r\n失败信息 %s", err.Error()))
		return
	}

	e.OK(resp, "success")
}

func (e LineUserApi) CallBack(c *gin.Context) {
	req := coingatedto.OrderCallBackResponse{}
	s := service.LineUser{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	err = s.CallBack(&req)

	if err != nil {
		val, _ := sonic.Marshal(req)
		e.Logger.Error("回调失败:", err.Error(), " \r\n回调内容：", string(val))
		e.Error(500, err, fmt.Sprintf("支付回调失败, \r\n失败信息 %s", err.Error()))
		return
	}

	e.OK(nil, "")
}

// 退出登录
func (e LineUserApi) Logout(c *gin.Context) {
	err := e.MakeContext(c).
		MakeOrm().
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	userId := common.GetUserId(c)
	err = authservice.Logout(userId, 1)

	if err != nil {
		logger.Error("退出登录失败:", err.Error())
		e.Error(statuscode.ServerError, nil, "")
	}

	e.OK(nil, "success")
}

// 查询个人资产
func (e LineUserApi) GetProperty(c *gin.Context) {
	s := service.LineUser{}
	err := e.MakeContext(c).
		MakeOrm().
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
	}

	var data dto.LineUserPropertyResp
	userId := common.GetUserId(c)
	code := s.GetProperty(userId, &data)
	if code != statuscode.OK && code != statuscode.UserApiUserNotBind {
		// e.Logger.Error(err)
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	e.OK(data, "success")
}

// 获取到期时间
func (e LineUserApi) GetUserInfo(c *gin.Context) {
	s := appservice.LineUser{}
	err := e.MakeContext(c).
		MakeOrm().
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
	}

	userId := common.GetUserId(c)
	var data dto.LineUserAppResp
	code := s.GetUserInfo(userId, &data)

	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	e.OK(data, "success")
}

// 用户下单设置
func (e LineUserApi) UserOrderSet(c *gin.Context) {
	s := service.LineUser{}
	req := dto.LineUserOrderSetReq{}

	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
	}

	userId := common.GetUserId(c)
	code := s.OrderSet(&req, userId)

	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	e.OK(nil, "success")
}

func (e LineUserApi) ResetPassword(c *gin.Context) {
	s := service.LineUser{}
	req := dto.LineUserResetPwdReq{}

	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
	}

	if code := req.Valid(); code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	code := s.ResetPassword(&req)

	if code != statuscode.OK {
		e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
		return
	}

	e.OK(nil, "success")
}
