// gin绑定参数模块
// 秒寻科技
// zt 2024-01-05

package bind

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"ipsomc/core/dao/mysql/mysqlmodel"
	"ipsomc/core/dao/redis/redismodel"
	"reflect"

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

type BindApi struct{}

// 绑定body中的参数
func (obj BindApi) bindBodyData(c *gin.Context, dataModel interface{}) error {
	//读取body参数后，参数将被清空
	bodyData, err := io.ReadAll(c.Request.Body)
	if err != nil {
		return err
	}
	defer c.Request.Body.Close()

	//body中没有数据
	if len(bodyData) <= 0 {
		return nil
	}

	//回写参数至body，以便执行bind
	r := bytes.NewBuffer(bodyData)
	rd := io.NopCloser(r)
	c.Request.Body = rd

	//绑定参数到模型
	if err := c.ShouldBindJSON(dataModel); err != nil {
		return errors.New("数据解析错误")
	}

	return nil
}

// 增加用户信息，包括用户ID、公司ID和项目信息
func (obj BindApi) AddUserInfo(c *gin.Context, dataModel interface{}) error {
	var redisModel redismodel.RedisOperator
	modelTmp, ok := c.Get("mycontext") //获得“mycontent”的值
	if ok {
		dataList, err := json.Marshal(modelTmp)
		if err != nil {
			return err
		}

		if err := json.Unmarshal(dataList, &redisModel); err != nil {
			return err
		}

		//将用户基本信息补充到模型中
		val := reflect.ValueOf(dataModel).Elem()
		val.FieldByName("CompanyID").SetInt(int64(redisModel.CompanyID))
		val.FieldByName("ProjectID").SetInt(int64(redisModel.ProjectID))
		val.FieldByName("OwnerID").SetInt(int64(redisModel.UserID))
	}

	return nil
}

// 绑定数据到模型
func (obj BindApi) Bind2Model(c *gin.Context, dataModel interface{}) error {
	if err := obj.bindBodyData(c, dataModel); err != nil {
		return err
	}

	//增加用户信息到模型
	if err := obj.AddUserInfo(c, dataModel); err != nil {
		return errors.New(err.Error())
	}

	return nil
}

// 绑定参数到map，用于修改模型
func (obj BindApi) Bind2Map(c *gin.Context, dataModel interface{}, dataMap map[string]interface{}) error {
	//将数据绑定到map中(只获得前端传过来的数据)
	if err := c.ShouldBindJSON(&dataMap); err != nil {
		return err
	}

	//将map转成结构体，以便填充dataModel
	dataList, err := json.Marshal(dataMap)
	if err != nil {
		return err
	}
	//填充dataModel（组要是填充ID值）
	if err := json.Unmarshal(dataList, dataModel); err != nil {
		return err
	}

	//从map中删除ID键
	for key := range dataMap {
		if key == "id" {
			delete(dataMap, key)
			break
		}
	}

	//增加用户信息到模型
	if err := obj.AddUserInfo(c, dataModel); err != nil {
		return errors.New(err.Error())
	}

	return nil
}

// 绑定参数到查询条件
func (obj BindApi) Bind2Query(c *gin.Context, queryParam interface{}) error {
	if err := obj.bindBodyData(c, queryParam); err != nil {
		return err
	}

	//增加用户信息到模型
	if err := obj.AddUserInfo(c, queryParam); err != nil {
		return errors.New(err.Error())
	}

	return nil
}

// 绑定数据到分页查询条件
func (obj BindApi) Bind2PageQuery(c *gin.Context, pageQueryParam *mysqlmodel.PageListParam) error {
	if err := obj.bindBodyData(c, pageQueryParam); err != nil {
		return err
	}

	//增加用户信息到模型
	if err := obj.AddUserInfo(c, pageQueryParam); err != nil {
		return errors.New(err.Error())
	}

	return nil
}
