package api

import (
	"bytes"
	"crypto/aes"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

// SendData 发送数据包
func SendData(urlStr string, data string, key string, method string, sendSignKey string, recSignKey string) map[string]interface{} {
	if method == "" {
		method = "POST"
	}

	var requestData = data
	if key != "-1" {
		requestData = Encrypt(data, key)
	}

	var sign string
	if sendSignKey != "" && recSignKey != "" { // 如果签名信息不为空
		sign = getMd5(strings.Replace(sendSignKey, "[KEY]", requestData, -1))
	}

	requestData = url.QueryEscape(requestData)

	var resp *http.Response
	var err error

	if method == "GET" {
		getURL := urlStr + "&parameter=" + requestData
		if sign != "" {
			getURL += "&sgin=" + sign
		}
		resp, err = http.Get(getURL)
	} else {
		formData := url.Values{}
		formData.Add("parameter", requestData)
		if sign != "" {
			formData.Add("sgin", sign)
		}
		resp, err = http.PostForm(urlStr, formData)
	}

	if err != nil {
		fmt.Println("HTTP请求错误:", err)
		return nil
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body) // 使用 io.ReadAll 替代 ioutil.ReadAll
	if err != nil {
		fmt.Println("读取响应错误:", err)
		return nil
	}

	// fmt.Println("return body:", string(body))

	var resultText string
	if key != "-1" {
		resultText = Decrypt(string(body), key)
	} else {
		resultText = string(body)
	}

	if resultText == "" {
		return nil
	}

	var result map[string]interface{}
	err = json.Unmarshal([]byte(resultText), &result)
	if err != nil {
		fmt.Println("JSON解析错误:", err)
		return nil
	}

	if sendSignKey != "" && recSignKey != "" { // 如果签名信息不为空
		responseData, ok := result["response"].(map[string]interface{})
		if !ok {
			return nil
		}

		data := responseData["data"].(string)
		date := responseData["date"].(string)
		unix := responseData["unix"].(string)
		microtime := responseData["microtime"].(string)
		appsafecode := responseData["appsafecode"].(string)

		verifySign := fmt.Sprintf("%s%s%s%s%s", data, date, unix, microtime, appsafecode)
		verifySign = strings.Replace(recSignKey, "[KEY]", verifySign, -1)
		sign = getMd5(verifySign)

		sgin, sginOk := responseData["sgin"].(string)
		sgin2, sgin2Ok := responseData["sgin2"].(string)

		if (!sginOk || sign != sgin) && (!sgin2Ok || sign != sgin2) {
			responseData["data"] = "sgin 签名验证不通过,自己写保护代码，golang也没啥可保护的"
		}
	}

	if respData, ok := result["response"].(map[string]interface{}); ok {
		return respData
	}
	return nil
}

// Encrypt AES-ECB加密
func Encrypt(data string, key string) string {
	md5Key := getMd5(key)[:16]
	block, err := aes.NewCipher([]byte(md5Key))
	if err != nil {
		return ""
	}

	paddedData := pkcs7Padding([]byte(data), block.BlockSize())
	ciphertext := make([]byte, len(paddedData))

	// ECB模式加密
	for bs, be := 0, block.BlockSize(); bs < len(paddedData); bs, be = bs+block.BlockSize(), be+block.BlockSize() {
		block.Encrypt(ciphertext[bs:be], paddedData[bs:be])
	}

	return base64.StdEncoding.EncodeToString(ciphertext)
}

// Decrypt AES-ECB解密
func Decrypt(data string, key string) string {
	ciphertext, err := base64.StdEncoding.DecodeString(data)
	if err != nil {
		return ""
	}

	md5Key := getMd5(key)[:16]
	block, err := aes.NewCipher([]byte(md5Key))
	if err != nil {
		return ""
	}

	plaintext := make([]byte, len(ciphertext))

	// ECB模式解密
	for bs, be := 0, block.BlockSize(); bs < len(ciphertext); bs, be = bs+block.BlockSize(), be+block.BlockSize() {
		block.Decrypt(plaintext[bs:be], ciphertext[bs:be])
	}

	return string(unpad(plaintext))
}

// pkcs7Padding 按PKCS#7标准填充数据
func pkcs7Padding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padtext...)
}

// unpad 去除PKCS#7填充
func unpad(data []byte) []byte {
	length := len(data)
	if length == 0 {
		return data
	}
	unpadding := int(data[length-1])
	return data[:(length - unpadding)]
}

// GetMiddleStr 取出中间文本
func GetMiddleStr(content string, startStr string, endStr string) string {
	startIndex := strings.Index(content, startStr)
	if startIndex >= 0 {
		startIndex += len(startStr)
	} else {
		return ""
	}
	endIndex := strings.Index(content[startIndex:], endStr)
	if endIndex < 0 {
		return ""
	}
	endIndex += startIndex
	return content[startIndex:endIndex]
}

// getMd5 计算字符串的MD5值
func getMd5(text string) string {
	hash := md5.New()
	hash.Write([]byte(text))
	return hex.EncodeToString(hash.Sum(nil))
}
