// Package response ...
//
// Description : response ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022-06-25 20:52
package response

import (
	"fmt"
	"git.zhangdeman.cn/zhangdeman/dynamic-struct/wrapper"
	"git.zhangdeman.cn/zhangdeman/serialize"
	"net/http"
	"strings"
	"time"

	"git.zhangdeman.cn/zhangdeman/exception"
	"git.zhangdeman.cn/zhangdeman/gin/define"
	"github.com/gin-gonic/gin"
)

const (
	// hasSendResponseFlag 已经发送响应数据的标识, 一旦识别到, 重复调用不会执行
	hasSendResponseFlag = "GIN_PKG_HAS_SEND_RESPONSE"
)

var (
	// 成功的业务状态码
	successBusinessCode any = "200"
)

// SetBusinessSuccessCode 设置成状态码
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2024/8/17
func SetBusinessSuccessCode(code any) {
	successBusinessCode = code
}

// Success 成功的响应
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:37 2022/6/25
func Success(ctx *gin.Context, data any) {
	successException := exception.NewSuccess(data)
	Send(ctx, successException.Code(), http.StatusOK, successException.Data(), nil)
}

// SuccessWithExtension 返回扩展数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:52 2024/9/24
func SuccessWithExtension(ctx *gin.Context, data any, responseOption *define.ResponseOption) {
	successException := exception.NewSuccess(data)
	Send(ctx, successException.Code(), http.StatusOK, successException.Data(), responseOption)
}

// Send 基础的发送数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:40 2022/6/25
func Send(ctx *gin.Context, code any, httpCode int, data any, responseOption *define.ResponseOption) {
	if nil == responseOption {
		responseOption = &define.ResponseOption{
			ContentType: "application/json; charset=utf-8",
			Extension:   make(map[string]any),
		}
	}
	if len(responseOption.ContentType) == 0 {
		responseOption.ContentType = "application/json; charset=utf-8"
	}
	if len(responseOption.XmlName) == 0 {
		responseOption.XmlName = "ResponseData"
	}
	// 设置请求是否成功的标识
	ctx.Set(define.GetHttpHandleConfig().RequestIsSuccessField, fmt.Sprintf("%v", code) == fmt.Sprintf("%v", successBusinessCode))
	if ctx.GetBool(hasSendResponseFlag) {
		// 已经发送过数据, 后面在发送数据, 不执行
		return
	}
	// 设置数据已发送的标识
	defer ctx.Set(hasSendResponseFlag, true)
	finishRequestTime := time.Now()
	responseData := BuildResponseData(ctx, finishRequestTime, code, data, responseOption.Extension)
	// 记录完成时间
	responseConfig := define.GetHttpHandleConfig()
	ctx.Set(responseConfig.FinishRequestTimeField, finishRequestTime.UnixMilli())
	ctx.Set(responseConfig.ResponseDataField, responseData)
	responseException := exception.New(code, responseData)
	responseContentType := getResponseDataType(responseOption.ContentType)
	responseStr := serialize.JSON.MarshalForStringIgnoreError(responseException.Data())
	if responseInstance, err := wrapper.NewJson(responseStr, &wrapper.Option{XmlName: responseOption.XmlName}); nil != err {
		// 接口处理成功, 数据序列化出现异常
		panic(err.Error()) // 直接panic, 交给gin处理
	} else {
		finalResponseData, _ := responseInstance.Marshal(responseContentType)
		ctx.Data(http.StatusOK, responseOption.ContentType, finalResponseData)
	}
}

// getResponseDataType 获取相应数据类型
func getResponseDataType(contentType string) string {
	if contentType == "" {
		return "json"
	}
	applicationInfo := strings.Split(contentType, ";")[0]
	applicationInfoArr := strings.Split(applicationInfo, "/")
	return applicationInfoArr[len(applicationInfoArr)-1]
}

// BuildResponseData 构建响应数据
func BuildResponseData(ctx *gin.Context, finishTime time.Time, code any, data any, extension map[string]any) map[string]any {
	responseConfig := define.GetHttpHandleConfig()
	responseData := map[string]any{
		responseConfig.ResponseCodeField:      code,
		responseConfig.ResponseMessageField:   exception.GetMessage(code),
		responseConfig.ResponseTraceIDField:   ctx.GetString(responseConfig.ResponseTraceIDField),
		responseConfig.ResponseDataField:      data,
		responseConfig.HandleRequestCostField: finishTime.UnixMilli() - ctx.GetInt64(responseConfig.StartRequestTimeField),
	}
	if responseConfig.EnableExtensionOutput && nil != extension {
		responseData[responseConfig.ExtensionOutputField] = extension
	}
	return responseData
}

// SendWithStatusOK ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:41 2022/6/25
func SendWithStatusOK(ctx *gin.Context, code any, data any) {
	Send(ctx, code, http.StatusOK, data, nil)
}

// SendWithException 使用exception发送数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 13:08 2022/6/26
func SendWithException(ctx *gin.Context, e exception.IException, responseOption *define.ResponseOption) {
	if nil == e {
		e = exception.NewSuccess(map[string]any{})
	}
	if !define.GetHttpHandleConfig().DisableDebugStackOutput && nil != e {
		stack := e.GetStack()
		if len(stack) > 0 {
			fmt.Println(stack)
		}
	}
	Send(ctx, e.Code(), http.StatusOK, e.Data(), responseOption)
}

// JSON ctx.JSON 的平替, 增加了数据是否已相应的标识
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:51 2023/2/15
func JSON(ctx *gin.Context, httpCode int, data any) {
	if ctx.GetBool(hasSendResponseFlag) {
		// 已经发送过数据, 后面在发送数据, 不执行
		return
	}
	// 设置数据已发送的标识
	defer ctx.Set(hasSendResponseFlag, true)
	ctx.JSON(httpCode, data)
}
