package trade

import (
	"errors"
	"mtp20access/client"
	"mtp20access/global"
	"mtp20access/model/common/response"
	"mtp20access/utils"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
)

// TradeConn 终端连接WebSocket
func TradeConn(c *gin.Context) (err error) {
	// 获取请求账号信息
	// s, exists := c.Get("claims")
	// if !exists {
	// 	err = errors.New("获取请求账号信息异常")
	// 	global.M2A_LOG.Error(err.Error())
	// 	return
	// }
	// claims := s.(*commonRequest.CustomClaims)

	// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
	token := c.Request.Header.Get("Sec-WebSocket-Protocol")
	if token == "" {
		response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
		c.Abort()
		return
	}

	j := utils.NewJWT()
	// parseToken 解析token包含的信息
	claims, err := j.ParseToken(token)
	if err != nil {
		if err == utils.ErrTokenExpired {
			response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_EXPIRED, "授权已过期", c)
			// c.Abort()
			return
		}
		response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
		// c.Abort()
		return
	}
	// 从Redis获取登录信息
	loginMap, err := j.GetRedisLogin(claims.LoginID, claims.Group)
	if err != nil {
		response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_OTHER_LOGIN, "您的帐户异地登陆或令牌失效", c)
		// c.Abort()
		return
	}
	// 判断Token是否有效
	if redisToken, isHas := loginMap["token"]; isHas {
		if redisToken != token {
			response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_OTHER_LOGIN, "您的帐户异地登陆或令牌失效", c)
			// c.Abort()
			return
		}
	} else {
		response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
		// c.Abort()
		return
	}

	// 获取登录账户信息
	client, exists := client.Clients[claims.SessionID]
	if !exists {
		err = errors.New("获取登录账户信息异常")
		global.M2A_LOG.Error(err.Error(), zap.Any("SessionID", claims.SessionID))
		return
	}

	// 需要注意的是，如果前端通过websocket连接时指定了Sec-WebSocket-Protocol，后端接收到连接后，必须原封不动的将Sec-WebSocket-Protocol头信息返回给前端，否则连接会抛出异常。
	// c.Header("Sec-WebSocket-Protocol", token)
	// c.String(200, "ok")
	// 将http连接升级为websocket连接
	upGrader := websocket.Upgrader{
		ReadBufferSize:  1000000,
		WriteBufferSize: 1000000,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
		//将获取的参数放进这个数组
		Subprotocols: []string{token},
	}
	ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		err = errors.New("连接错误")
		global.M2A_LOG.Error("将http连接升级为websocket连接失败", zap.Any("err", err))
		return
	}

	client.SetTradeWebSocket(ws)

	return
}
