package controllers

import (
	"github.com/LyricTian/captcha"
	"github.com/gogf/gf/v2/net/ghttp"
	"yx-dataset-server/app/bll"
	"yx-dataset-server/app/errors"
	"yx-dataset-server/app/schema"
	"yx-dataset-server/library/gplus"
	"yx-dataset-server/library/logger"
	"yx-dataset-server/library/utils"
)

func NewLogin(
	bLogin bll.ILogin,
	bVerify bll.IVerifyCode,
	bUser bll.IUser,
) *Login {
	return &Login{
		bLogin:  bLogin,
		bVerify: bVerify,
		bUser:   bUser,
	}
}

type Login struct {
	bLogin  bll.ILogin
	bVerify bll.IVerifyCode
	bUser   bll.IUser
}

// GetCaptchaID 获取验证码ID
// @Summary 获取验证码ID
// @Success 200 schema.LoginCaptcha
// @Router GET /web/v1/login/captchaid
func (a *Login) GetCaptchaID(r *ghttp.Request) {
	ctx := gplus.NewContext(r)
	item, err := a.bLogin.GetCaptchaID(ctx, utils.GetConfig("captcha.length").Int())
	if err != nil {
		ResError(r, err)
		return
	}
	ResSuccess(r, item)
}

// GetCaptcha 获取图形验证码
// @Summary 获取图形验证码
// @Param id query string true "验证码ID"
// @Param reload query string false "重新加载"
// @Success 200 file "图形验证码"
// @Failure 400 schema.HTTPError "{error:{code:0,message:无效的请求参数}}"
// @Failure 500 schema.HTTPError "{error:{code:0,message:服务器错误}}"
// @Router GET /web/v1/login/captcha
func (a *Login) GetCaptcha(r *ghttp.Request) {
	ctx := gplus.NewContext(r)
	captchaID := r.Get("id").String()
	if captchaID == "" {
		ResError(r, errors.ErrBadRequest)
		return
	}

	if r.Get("reload").String() != "" {
		if !captcha.Reload(captchaID) {
			ResError(r, errors.ErrBadRequest)
			return
		}
	}

	err := a.bLogin.ResCaptcha(ctx, r.Response.ResponseWriter, captchaID, utils.GetConfig("captcha.width").Int(), utils.GetConfig("captcha.height").Int())
	if err != nil {
		ResError(r, err)
	}
}

// Login 用户登录
// @Summary 用户登录
// @Param body schema.LoginParam true
// @Success 200 schema.LoginTokenInfo "{access_token:访问令牌,token_type:令牌类型,expires_in:过期时长(单位秒)}"
// @Failure 400 schema.HTTPError "{error:{code:0,message:无效的请求参数}}"
// @Failure 500 schema.HTTPError "{error:{code:0,message:服务器错误}}"
// @Router POST /web/v1/login
func (a *Login) Login(r *ghttp.Request) {
	var item schema.LoginParam
	ctx := gplus.NewContext(r)
	if err := gplus.ParseJson(r, &item); err != nil {
		ResError(r, err)
		return
	}

	if !captcha.VerifyString(item.CaptchaID, item.CaptchaCode) {
		ResError(r, errors.New400Response("无效的验证码"))
		return
	}

	user, err := a.bLogin.Verify(ctx, item.UserName, item.Password)
	if err != nil {
		ResError(r, err)
		return
	}
	// 将用户ID放入上下文
	gplus.SetUserId(r, user.RecordID)

	tokenInfo, err := a.bLogin.GenerateToken(ctx, user.RecordID)
	if err != nil {
		ResError(r, err)
		return
	}
	logger.StartSpan(gplus.NewContext(r), logger.SetSpanTitle("用户登录"), logger.SetSpanFuncName("Login")).Infof(ctx, "登入系统")
	ResSuccess(r, tokenInfo)
}

// Logout 用户登出
// @Summary 用户登出
// @Success 200 schema.HTTPStatus "{status:OK}"
// @Router POST /web/v1/login/exit
func (a *Login) Logout(r *ghttp.Request) {
	// 检查用户是否处于登录状态，如果是则执行销毁
	userID := gplus.GetUserID(r)
	ctx := gplus.NewContext(r)
	if userID != "" {
		err := a.bLogin.DestroyToken(ctx, gplus.GetToken(r))
		if err != nil {
			logger.Errorf(ctx, err.Error())
		}
		logger.StartSpan(gplus.NewContext(r), logger.SetSpanTitle("用户登出"), logger.SetSpanFuncName("Logout")).Infof(ctx, "登出系统")
	}
	ResSuccess(r, nil)
}

// GetUserInfo 获取当前用户信息
// @Router GET /web/v1/current/user
func (a *Login) GetUserInfo(r *ghttp.Request) {
	ctx := gplus.NewContext(r)
	userId := gplus.GetUserID(r)
	info, err := a.bUser.GetCurrentUser(ctx, userId)
	if err != nil {
		ResError(r, err)
		return
	}
	ResSuccess(r, info)
}

// UpdatePassword 更新个人密码
// @Summary 更新个人密码
// @Param body  schema.UpdatePasswordParam true
// @Success 200 schema.HTTPStatus "{status:OK}"
// @Failure 400 schema.HTTPError "{error:{code:0,message:无效的请求参数}}"
// @Failure 401 schema.HTTPError "{error:{code:0,message:未授权}}"
// @Failure 500 schema.HTTPError "{error:{code:0,message:服务器错误}}"
// @Router PUT /web/v1/current/password
func (a *Login) UpdatePassword(r *ghttp.Request) {
	ctx := gplus.NewContext(r)
	var item schema.UpdatePasswordParam
	if err := gplus.ParseJson(r, &item); err != nil {
		ResError(r, err)
		return
	}

	err := a.bLogin.UpdatePassword(ctx, item)
	if err != nil {
		ResError(r, err)
		return
	}
	ResSuccess(r, nil)
}

// @Router POST /web/v1/login/code
func (a *Login) Send(r *ghttp.Request) {

	req := schema.VerifyCodeRequest{}
	if err := gplus.ParseJson(r, &req); err != nil {
		ResError(r, err)
	}

	ctx := gplus.NewContext(r)
	item, err := a.bVerify.ALiYunSendSms(ctx, req)
	if err != nil {
		ResError(r, err)
	}
	ResSuccess(r, item)
}

// @Router POST /web/v1/login/sms
func (a *Login) LoginBySms(r *ghttp.Request) {
	var params schema.SmsLoginParam
	params.BusinessType = 1
	ctx := gplus.NewContext(r)
	if err := gplus.ParseJson(r, &params); err != nil {
		ResError(r, err)
	}
	err := a.bLogin.LoginBySms(ctx, params)
	if err != nil {
		ResError(r, err)
	}

	ResSuccess(r, nil)
}

// RefreshToken 刷新令牌
func (a *Login) RefreshToken(r *ghttp.Request) {
	ctx := gplus.NewContext(r)
	token, err := a.bLogin.RefreshToken(ctx)
	if err != nil {
		ResError(r, err)
	}
	ResSuccess(r, token)
}
