package wx

import (
	"encoding/json"
	"fmt"
	"io"
	"mini_server/internal/config"
	"mini_server/internal/dao"
	"mini_server/internal/middleware/jwt"
	"mini_server/internal/server/help"
	"mini_server/internal/server/httpreply"
	"mini_server/internal/server/user"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

type LoginRequest struct {
	Code string `json:"code" binding:"min=1"` // 临时会话登录code
}

type LoginReply struct {
	Token    string         `json:"token"` // 返回登录成功的jwt token
	UserInfo *user.UserInfo `json:"user_info"`
}

// 微信服务器，返回的数据结构
type WxHttpReply struct {
	Errcode int32  `json:"errcode"` // 错误码
	Errmsg  string `json:"errmsg"`  // 错误信息
	OpenId  string `json:"openid"`  // 用户唯一标识
	// Unionid    string `json:"unionid"` 	// 用户在开放平台的唯一标识符，在满足 UnionID 下发条件的情况下会返回，详见微信 UnionID
	SessionKey string `json:"session_key"` // 会话密钥
}

func WxLogin(c *gin.Context) {
	reply := httpreply.NewDefaultReplyData()
	defer httpreply.Reply(c, reply)

	//解析请求参数
	var request LoginRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		reply.Status = http.StatusBadRequest
		reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
		return
	}
	logrus.Tracef("微信登录，请求参数:%v", request)

	// 从微信查询openId
	openId, err := get_wx_login_open_id(request.Code)
	if err != nil {
		logrus.Errorf("请求微信获取OpenId失败，err:%v", err)
		reply.Status = http.StatusServiceUnavailable
		reply.Message = "第三方服务错误"
		return
	}

	// 首先查询，是否存在
	data, err := dao.User_WX_Query(openId)
	if err != nil {
		logrus.Errorf("微信登录，数据库查询失败,err：%v", err)
		reply.Status = http.StatusInternalServerError
		reply.Message = "用户查询失败"
		return
	}

	if data == nil { // 用户不存在，则需要添加创建

		default_wx_username, err := get_default_wx_username()
		if err != nil {
			logrus.Errorf("生成微信默认用户名失败,err:%v", err)
			reply.Status = http.StatusInternalServerError
			reply.Message = "生成微信默认用户名失败"
			return
		}

		data = &dao.User{
			AvatarId: "",
			OpenId:   openId,
			Username: default_wx_username, // 默认名称
			Persona:  "{}",
			Tags:     "{}",
		}

		if _, err = dao.User_WX_Insert(data); err != nil {
			logrus.Errorf("微信登录，数据库用户添加失败,err：%v", err)
			reply.Status = http.StatusInternalServerError
			reply.Message = "用户添加失败"
			return
		}
	}

	// 生成token
	token, err := jwt.CreateToken(data)
	if err != nil {
		logrus.Errorf("微信登录，生成token失败，err:%v", err)
		reply.Status = http.StatusInternalServerError
		reply.Message = "token生成失败"
		return
	}

	// 返回用户信息
	var info user.UserInfo
	user.Copy_User_Info(data, &info)
	loginReply := LoginReply{
		Token:    token,
		UserInfo: &info,
	}
	reply.Data = &loginReply
	logrus.Tracef("微信登录成功，应答:%v", reply)
}

func get_wx_login_open_id(code string) (string, error) {
	//接口请求url拼接
	url := config.WeiXin.AppUrl(code)

	// 转发请求到微信接口
	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("请求微信登录接口失败，err:%v", err)
	}
	defer resp.Body.Close()

	// 读取数据
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取微信登录应答数据失败，err:%v", err)
	}

	// 解码数据并赋值给返回的respData
	respData := new(WxHttpReply)
	json.Unmarshal(body, &respData)

	openId := respData.OpenId
	// 检测openid是否为空
	if openId == "" {
		return "", fmt.Errorf("读取微信登录应答数据openId为空")
	}
	return openId, nil
}

// 注册时返回随机名称
func get_default_wx_username() (string, error) {
	id := help.GetUniqueIdEachSecond()
	return "微信用户" + id, nil
}
