package controllers

import (
	"encoding/json"
	"fmt"
	"strings"
	"sws_xcx/enums"
	"sws_xcx/models"
	"sws_xcx/service"
	"sws_xcx/utils"

	"net/http"
	"time"

	"github.com/astaxie/beego"
	"github.com/dgrijalva/jwt-go"
	"github.com/google/uuid"
)

func ApiControllersRegisterRouters() {

	//接收MQTT消息
	beego.Router("/xcx/api/device/emqmsg", &MessageApiControllor{}, "Post:PutEmqxMessage")

	beego.Router("/xcx/api/user/login", &LoginApiController{}, "Post:WxXcxLogin")

	beego.Router("/xcx/api/user/updatephonebycode", &UserApiController{}, "Post:UpdatePhoneByCode")

	beego.Router("/xcx/api/user/getuserinfo", &UserApiController{}, "Get:GetUserInfo")

	beego.Router("/xcx/api/user/savehealthprofile", &UserApiController{}, "Post:SaveHealthProfile")

	beego.Router("/xcx/api/user/saveuserinfo", &UserApiController{}, "Post:SaveUserInfo")

	beego.Router("/xcx/api/user/gethealthprofile", &UserApiController{}, "Get:GetHealthProfile")

	beego.Router("/xcx/api/sysdic/getillness", &SysDicApiController{}, "Get:GetIllness")

	beego.Router("/xcx/api/sysdic/getrenalstatus", &SysDicApiController{}, "Get:GetRenalStatus")

}

type BaseApiController struct {
	beego.Controller
}

func (c *BaseApiController) Prepare() {
}

type BaseApiAuthController struct {
	BaseApiController
	CurrentUser models.XcxUser
	sessionKey  string
}

func (c *BaseApiAuthController) Prepare() {
	c.BaseApiController.Prepare()
	// JWT Token通常放在请求头中，例如Authorization: Bearer <token>
	authHeader := c.Ctx.Input.Header("Authorization")
	if authHeader == "" {
		c.ServeFailJsonSendAndStop(http.StatusUnauthorized, enums.ErrorCodeNotLogin, "缺少认证信息")
		return
	}
	tokenString := authHeader
	if strings.Contains(authHeader, "Bearer") {
		tokenString = authHeader[len("Bearer "):]
	}

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		//从配置文件中获取secret
		secret := beego.AppConfig.String("xsrfkey")
		return []byte(secret), nil
	})

	if err != nil || !token.Valid {
		utils.ErrorLog("Token验证失败: %v", err)
		c.ServeFailJsonSendAndStop(http.StatusUnauthorized, enums.ErrorCodeNotLogin, "无效的Token")
		return
	}

	// 假设JWT中包含了用户ID
	claims, ok := token.Claims.(CustomClaims)
	if !ok {
		c.ServeFailJsonSendAndStop(http.StatusUnauthorized, enums.ErrorCodeNotLogin, "无法解析Token中的信息")
		return
	}

	key := claims.UserID
	c.sessionKey = key
	redisCli := service.RedisClient()
	defer redisCli.Close()
	uJson, err := redisCli.Get(key).Bytes()

	if err != nil {
		c.ServeFailJsonSendAndStop(http.StatusUnauthorized, enums.ErrorCodeNotLogin, fmt.Sprintf("redis err:%v", err))
		return
	}

	user := &models.XcxUser{}
	err = json.Unmarshal(uJson, user)
	if err != nil {
		c.ServeFailJsonSendAndStop(http.StatusUnauthorized, enums.ErrorCodeNotLogin, fmt.Sprintf("json err:%v", err))
		return
	}
	//c.Ctx.Input.SetData("user", user)
	c.CurrentUser = *user
	//c.SetSession("user", user)
}

type CustomClaims struct {
	UserID string `json:"sessionkey"`
	jwt.StandardClaims
}

// 输出数据格式化
/*
	success json:
	{
		"state": 1,
		"code": 0,
		"data": json,
	}

	fail json:
	{
		"state": 0,
		"code": int,
		"msg": string,
	}
*/
func (c *BaseApiController) ServeSuccessJSON(data interface{}) {
	c.Data["json"] = enums.MakeSuccessResponseJSON(data)
	c.ServeJSON()
}

func (c *BaseApiController) ServeFailJSONWithSGJErrorCode(code int) {
	c.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(code)
	c.ServeJSON()
}

func (c *BaseApiController) ServeFailJSONWithSGJError(err *enums.SGJError) {
	c.Data["json"] = enums.MakeFailResponseJSONWithSGJError(err)
	c.ServeJSON()
}

func (c *BaseApiController) ServeFailJsonSend(code int, msg string) {
	c.Data["json"] = enums.MakeFailResponseJSON(msg, code)
	c.ServeJSON()
}

func (c *BaseApiController) ServeDynamicFailJsonSend(msg string) {
	c.Data["json"] = enums.MakeDynamicFailResponseJSON(msg)
	c.ServeJSON()
}
func (c *BaseApiController) ServeFailJsonSendAndStop(httpStatus int, errCode int, msg string) {
	c.Ctx.Output.SetStatus(httpStatus)
	c.ServeFailJsonSend(errCode, msg)
	c.StopRun()
}

func (c *BaseApiController) login(u models.XcxUser) (string, error) {

	key := uuid.New().String()
	expire, _ := beego.AppConfig.Int("xsrfexpire")

	if expire == 0 {
		expire = 7200
	}
	uJson, _ := json.Marshal(u)
	redisCli := service.RedisClient()
	defer redisCli.Close()
	service.RedisClient().Set(key, uJson, time.Second*time.Duration(expire))
	// 创建一个我们自己的声明
	claims := CustomClaims{
		UserID: key,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Second * time.Duration(expire)).Unix(), // Token有效期（默认为7200秒）
			Issuer:    "sws_xcx",                                                  // 签发者
		},
	}

	// 使用指定的签名方法创建签名
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 使用密钥签名并获得完整的编码后的字符串形式的Token
	return token.SignedString([]byte(beego.AppConfig.String("xsrfkey")))
}
func (c *BaseApiAuthController) updateCurrentUser(updateAction func(*models.XcxUser)) error {
	u := &c.CurrentUser
	updateAction(u)
	err := service.NewXcxUserService().UpdateUser(u)
	if err != nil {
		//c.ServeFailJsonSendAndStop(http.StatusOK, enums.ErrorCodeDBUpdate, "更新用户信息失败")
		return err
	}

	redisCli := service.RedisClient()
	defer redisCli.Close()
	uJson, _ := json.Marshal(u)
	expire, _ := beego.AppConfig.Int("xsrfexpire")

	if expire == 0 {
		expire = 7200
	}
	err = redisCli.Set(c.sessionKey, uJson, time.Second*time.Duration(expire)).Err()
	if err != nil {
		return err
	}

	c.CurrentUser = *u

	return nil

}
