// Package parse_body ...
//
// Description : parse_body ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-10-22 16:43
package parse_body

import (
	"bytes"
	"errors"
	"git.zhangdeman.cn/zhangdeman/gin/request/abstract"
	"git.zhangdeman.cn/zhangdeman/serialize"
	"github.com/gin-gonic/gin"
	"io"
	"strings"
)

var (
	requestBodyParseAdaptorTable = map[string]abstract.RequestBodyParseAdaptor{}
)

func init() {
	requestBodyParseAdaptorTable["xml"] = serialize.Xml
	requestBodyParseAdaptorTable["ini"] = serialize.Ini
	requestBodyParseAdaptorTable["yml"] = serialize.Yml
	requestBodyParseAdaptorTable["yaml"] = serialize.Yml
	requestBodyParseAdaptorTable["json"] = serialize.JSON
	requestBodyParseAdaptorTable["x-www-form-urlencoded"] = serialize.JSON
}

// Register 注册适配器实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:45 2024/10/22
func Register(requestType string, adaptor abstract.RequestBodyParseAdaptor) {
	if nil == adaptor {
		return
	}
	requestBodyParseAdaptorTable[requestType] = adaptor
}

// Execute 解析请求BODY数据
func Execute(ctx *gin.Context, receiver any) ([]byte, error) {
	contentType := strings.ToLower(strings.ReplaceAll(ctx.ContentType(), " ", ""))
	if len(contentType) == 0 {
		return []byte("{}"), nil
	}
	// 裁剪出真实的类型，之所以截取，是因为 content_type 中可能还包含编码信息, 如 : application/json;chaset=utf8
	contentTypeArr := strings.Split(contentType, ";")
	contentTypeFormatArr := strings.Split(contentTypeArr[0], "/")
	if len(contentTypeFormatArr) != 2 {
		return nil, errors.New(contentType + " : content_type format error")
	}
	// 裁剪出真实的类型，之所以截取，是因为 content_type 中可能还包含编码信息, 如 : application/json;charset=utf8
	contentType = contentTypeFormatArr[1]
	if _, exist := requestBodyParseAdaptorTable[contentType]; !exist {
		return nil, errors.New(contentType + " : adaptor not found")
	}
	var (
		bodyData []byte
		err      error
		exist    bool
		body     any
	)

	bodyKey := "_body_read_result"
	if body, exist = ctx.Get(bodyKey); exist && nil != body {
		bodyData = body.([]byte)
	} else {
		if bodyData, err = ReadBody(ctx); nil != err {
			return nil, err
		}
		// 设置读取结果
		ctx.Set(bodyKey, bodyData)
	}

	if err = requestBodyParseAdaptorTable[contentType].Unmarshal(bodyData, receiver); nil != err {
		return nil, err
	}
	byteData := serialize.JSON.MarshalForByteIgnoreError(receiver)
	return byteData, nil
}

// ExecuteForMap 高层级包装，表单解析为map
func ExecuteForMap(ctx *gin.Context) (map[string]any, error) {
	var (
		err    error
		result map[string]any
	)
	if _, err = Execute(ctx, &result); nil != err {
		return nil, err
	}
	return result, nil
}

// ReadBody 读取请求Body
func ReadBody(ctx *gin.Context) ([]byte, error) {
	var (
		data []byte
		err  error
	)
	// 判断form url encode
	if strings.Contains(ctx.ContentType(), "x-www-form-urlencoded") {
		if err = ctx.Request.ParseForm(); nil != err {
			return nil, err
		}
		body := map[string]any{}
		for paramName, itemParam := range ctx.Request.PostForm {
			if len(itemParam) > 0 {
				body[paramName] = itemParam[0]
			} else {
				body[paramName] = ""
			}
		}
		return serialize.JSON.MarshalForByteIgnoreError(body), nil
	}

	// 读取Body信息
	if data, err = io.ReadAll(ctx.Request.Body); nil != err {
		return nil, err
	}
	// 重置Body信息
	ctx.Request.Body = io.NopCloser(bytes.NewBuffer(data))
	return data, nil
}
