package main

import (
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
)

// Token should be replaced with the developer's own token
const token = "your token"

func main() {
	router := gin.Default()
	router.Any("/application-demo/postprocess", postprocess)
	router.Run(":8080")
}

func postprocess(c *gin.Context) {
	if c.Request.Method == http.MethodPost {
		receiveMessage(c)
	} else if c.Request.Method == http.MethodGet {
		serverAccessVerify(c)
	} else {
		c.String(http.StatusMethodNotAllowed, "Method Not Allowed")
	}
}

func receiveMessage(c *gin.Context) {
	fmt.Println("消息验证开始 >>>")

	msgsignature := c.Query("msgsignature")
	timestamp := c.Query("timestamp")
	rand := c.Query("rand")

	bodyBytes, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusInternalServerError, "Error reading body")
		return
	}
	body := string(bodyBytes)
	fmt.Printf("Received Body: %s\n", body)

	flag := checkSignature(msgsignature, token, rand, timestamp, body)
	if flag {
		fmt.Println(">>> 消息验证通过")
	} else {
		fmt.Println(">>> 消息验证未通过")
		c.String(http.StatusForbidden, "Forbidden")
		return
	}

	fmt.Println("解析消息主体 >>>")
	var response string
	if body != "" {
		var jsonBody map[string]interface{}
		if err := json.Unmarshal(bodyBytes, &jsonBody); err != nil {
			c.String(http.StatusBadRequest, "Invalid JSON")
			return
		}

		fromSub := jsonBody["FromSub"].(string)
		if fromSub == "iat" {
			response = body
		} else if fromSub == "kc" {
			response = handleNlpResult(jsonBody)
			fmt.Printf("语义处理结果：%s\n", response)
		}
	}
	fmt.Println(">>> 消息解析结束")

	if response == "" {
		response = body
	}
	c.String(http.StatusOK, response)
}

func handleNlpResult(jsonBody map[string]interface{}) string {
	msg := jsonBody["Msg"].(map[string]interface{})
	if msg != nil && msg["ContentType"].(string) == "json" {
		decodedContent, err := base64.StdEncoding.DecodeString(msg["Content"].(string))
		if err != nil {
			fmt.Println("Error decoding content:", err)
			return ""
		}
		content := string(decodedContent)
		fmt.Printf("Decoded Content: %s\n", content)

		var jsonContent map[string]interface{}
		if err := json.Unmarshal(decodedContent, &jsonContent); err != nil {
			fmt.Println("Error unmarshalling content:", err)
			return ""
		}

		intent := jsonContent["intent"].(map[string]interface{})
		answer := intent["answer"]
		if answer != nil {
			resMap := map[string]interface{}{
				"intent": map[string]interface{}{
					"answer": answer,
				},
			}
			responseBytes, err := json.Marshal(resMap)
			if err != nil {
				fmt.Println("Error marshalling response:", err)
				return ""
			}
			return string(responseBytes)
		}
	}
	return ""
}

func serverAccessVerify(c *gin.Context) {
	fmt.Println("服务器接入验证开始 >>>")

	rand := c.Query("rand")
	timestamp := c.Query("timestamp")
	signature := c.Query("signature")

	flag := checkSignature(signature, token, rand, timestamp)
	if flag {
		fmt.Println(">>> 服务器接入验证通过")
		sha1Token := sha1Hash(token)
		c.String(http.StatusOK, sha1Token)
	} else {
		fmt.Println(">>> 服务器接入验证未通过")
		c.String(http.StatusForbidden, "Forbidden")
	}
}

func checkSignature(signature string, args ...string) bool {
	sort.Strings(args)
	sign := strings.Join(args, "")
	tmpStr := sha1Hash(sign)
	return signature == tmpStr
}

func sha1Hash(str string) string {
	h := sha1.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}
