package controllers

import (
	"encoding/json"
	"fmt"
	"oppmg/common/log"
	"oppmg/protocol"
	serveauth "oppmg/services/auth"
	"oppmg/services/ucenter"
	"oppmg/storage/redisdata"
	"strconv"
	"time"

	"github.com/GeeTeam/gt3-golang-sdk/geetest"
)

//AuthController  授权认证相关
type AuthController struct {
	BaseController
}

//URLMapping 实现ControllerInterface中的URLMapping
func (c *AuthController) URLMapping() {
	c.Mapping("RefreshToken", c.RefreshToken)
}

// RefreshToken ....
// @router /refresh_token [get]
func (c *AuthController) RefreshToken() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()
	companyid := c.GetCompanyId()
	userid := c.GetUserId()
	logintoken, err := serveauth.ChangeLoginToken(userid, companyid)
	if err != nil {
		msg = protocol.NewReturnResponse(nil, err)
		return
	}
	err = serveauth.ResetLoginTokenRedis(logintoken)
	data := protocol.ResponseLogin{
		Access: logintoken,
	}
	msg = protocol.NewReturnResponse(data, err)
	return
}

// Login 登录
// @router /login [post]
func (c *AuthController) Login() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()

	var param protocol.RequestLogin
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	if len(param.Account) == 0 || len(param.Password) == 0 {
		msg = protocol.BadRequestParam("10201")
		return
	}
	logintoken, err := serveauth.LoginAuthByUCenter(param.Account, param.Password)
	if err != nil {
		msg = protocol.NewReturnResponse(nil, err)
		return
	}
	err = serveauth.ResetLoginToken(logintoken)
	if err != nil {
		log.Error("token 信息记录数据库失败")
	}
	err = serveauth.ResetLoginTokenRedis(logintoken)
	if err != nil {
		log.Error("token 信息记录redis失败")
	}
	data := protocol.ResponseLogin{
		Access: logintoken,
	}
	msg = protocol.NewReturnResponse(data, nil)
	return
}

// LoginSms 短信验证码登录
// @router /login_sms [post]
func (c *AuthController) LoginSms() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()

	var param protocol.RequestLoginSms
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	if len(param.Account) == 0 || len(param.Code) == 0 {
		msg = protocol.BadRequestParam("10201")
		return
	}
	var uclientReturn *ucenter.ResponseLoginSms
	uclientReturn, err := ucenter.RequestUCenterLoginSms(param.Account, param.Code)
	if err != nil {
		if uclientReturn != nil {
			msg = &protocol.ResponseMessage{
				Errno:  -1,
				Errmsg: uclientReturn.Msg,
				Data:   protocol.NullData,
			}
		} else {
			msg = protocol.NewMessage("10208")
		}
		return
	}
	logintoken, err := serveauth.LoginAuthBySmsCode(uclientReturn)
	if err == nil {
		err = serveauth.ResetLoginToken(logintoken)
		if err != nil {
			log.Error("token 信息记录数据库失败")
		}
		err = serveauth.ResetLoginTokenRedis(logintoken)
		if err != nil {
			log.Error("token 信息记录redis失败")
		}
	}
	data := protocol.ResponseLogin{
		Access: logintoken,
	}
	msg = protocol.NewReturnResponse(data, err)
	return
}

// LoginSecret 使用秘钥进行登录
// @router /login [post]
func (c *AuthController) LoginSecretKey() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()
	type Parameter struct {
		Secret string `json:"secret"`
	}
	var param Parameter
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	if len(param.Secret) == 0 {
		msg = protocol.BadRequestParam("10210")
		return
	}
	logintoken, err := serveauth.LoginAuthBySecretKey(param.Secret)
	if err != nil {
		msg = &protocol.ResponseMessage{
			Errno:  -1,
			Errmsg: err.Error(),
		}
		return
	}
	err = serveauth.ResetLoginToken(logintoken)
	if err != nil {
		log.Error("token 信息记录数据库失败")
	}
	err = serveauth.ResetLoginTokenRedis(logintoken)
	if err != nil {
		log.Error("token 信息记录redis失败")
	}
	data := protocol.ResponseLogin{
		Access: logintoken,
	}
	msg = protocol.NewReturnResponse(data, nil)
	return
}

//SmsCode 发送验证码短信
//@router /auth/smscode
func (c *AuthController) SmsCode() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()
	type Parameter struct {
		Phone string `json:"phone"`
	}
	var param Parameter
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	if len(param.Phone) == 0 {
		msg = protocol.BadRequestParam("1")
		return
	}
	err := serveauth.SmsCodeSend(param.Phone)
	msg = protocol.NewReturnResponse(nil, err)
	return
}

//SmsCode 验证码短信校验
//@router /auth/smscode/check
func (c *AuthController) SmsCodeCheck() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()
	type Parameter struct {
		Phone string `json:"phone"`
		Code  string `json:"code"`
	}
	var param Parameter
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	if len(param.Phone) == 0 {
		msg = protocol.BadRequestParam("1")
		return
	}
	err := serveauth.SmsCodeCheck(param.Phone, param.Code)
	msg = protocol.NewReturnResponse(nil, err)
	return
}

//ChangeCompany 切换公司
//@Router /change_company [post]
func (c *AuthController) ChangeCompany() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()

	var param protocol.RequestSwapCompany
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
		log.Error("json 解析失败", err)
		msg = protocol.BadRequestParam("1")
		return
	}
	userid := c.GetUserId()
	if param.CompanyId <= 0 {
		msg = protocol.BadRequestParam("1")
		return
	}
	logintoken, err := serveauth.ChangeLoginToken(userid, param.CompanyId)
	if err != nil {
		msg = protocol.NewReturnResponse(nil, err)
		return
	}
	err = serveauth.ResetLoginToken(logintoken)
	if err != nil {
		log.Error("token 信息记录数据库失败")
	}
	err = redisdata.SetLoginToken(logintoken, userid, param.CompanyId)
	if err != nil {
		log.Error("redisdata.SetLoginToken err:%s", err)
	}
	data := protocol.ResponseLogin{
		Access: logintoken,
	}
	msg = protocol.NewReturnResponse(data, err)
	return
}

//Me 。。
//@router /me [get]
func (c *AuthController) Me() {
	var msg *protocol.ResponseMessage
	defer func() {
		c.ResposeJson(msg)
	}()
	userid := c.GetUserId()
	companyid := c.GetCompanyId()
	userinfo, err := serveauth.UserBaseInfo(userid, companyid)
	if err != nil {
		log.Error("获取用户数据失败")
	}
	menus, err := serveauth.GetUserHasMenu(userid, companyid)
	if err != nil {
		log.Error("获取用户菜单失败")
	}
	companys, err := serveauth.UserHasCompanys(userid)
	if err != nil {
		log.Error("获取用户的公司失败")
	}
	permissionMap := serveauth.GetUserMenuPermission(userid, companyid)
	data := map[string]interface{}{
		"user":       userinfo,
		"menus":      menus,
		"companys":   companys,
		"permission": permissionMap,
	}
	msg = protocol.NewReturnResponse(data, nil)
	return
}

const (
	captchaID  = "33a2abf9c5df0d6bc3b89fb39280114b"
	privateKey = "13320fd2b10199e9a2440a4fbb4d46f7"
)

// RegisterGeetest  极验初始化
func (c *AuthController) RegisterGeetest() {
	geetest := geetest.NewGeetestLib(captchaID, privateKey, 2*time.Second)
	userip := c.Ctx.Input.IP()
	status, responseBt := geetest.PreProcess("", userip)
	c.SetSession("geetest_status", status)
	c.Ctx.Output.Body(responseBt)
	return
}

// RegisterGeetest  极验初校验
func (c *AuthController) ValidateGeetest() {
	type Parameter struct {
		GeetestChallenge string `form:"geetest_challenge"`
		GeetestValidate  string `form:"geetest_validate"`
		GeetestSeccode   string `form:"geetest_seccode"`
	}

	var (
		param      Parameter
		geetestRes bool
		status     int
	)
	err := c.ParseForm(&param)
	if err != nil {
		log.Error("解析表单数据失败;%s", err)
	}
	val := c.GetSession("geetest_status")
	status, _ = strconv.Atoi(fmt.Sprint(val))
	geetest := geetest.NewGeetestLib(captchaID, privateKey, 2*time.Second)
	if status == 1 {
		geetestRes = geetest.SuccessValidate(param.GeetestChallenge, param.GeetestValidate, param.GeetestSeccode, "", "")
	} else {
		geetestRes = geetest.FailbackValidate(param.GeetestChallenge, param.GeetestValidate, param.GeetestSeccode)
	}
	res := make(map[string]interface{})
	if geetestRes {
		res["code"] = 0
		res["msg"] = "Success"
	} else {
		res["code"] = -100
		res["msg"] = "Failed"
	}
	responseBt, _ := json.Marshal(res)
	c.Ctx.Output.Body(responseBt)
	return
}