package asign

import (
	"bytes"
	"encoding/json"
	"mtp20access/global"
	"os/exec"
	"strings"

	"go.uber.org/zap"
)

// 签名规范：
//
//	1、表单提交方式：form-data
//	2、请求头部参数
//	    参数1：sign（签名值，具体算法参考一下的前面算法）
//	    参数2：timestamp（时间戳，13位）
//	3、请求体参数：
//	    参数1：appId（appId值，每个接入者唯一一个）
//	    参数2：timestamp（时间戳，13位，与上述一致）
//	    参数3：bizData（json字符串，举个例子，比方说要传合同编号如：{"contractNo":"0001"}）
//	4、签名算法：
//	    4.1、将上述3所属的bizData（json字符串），按照阿拉伯字母排序(如：{"ba":1,"ac":2}--->{"ac":2,"ba":1})，
//	    4.2、将4.1排序后的字符串，将【bizData+md5（bizData）+ appId + timestatmp】拼接后利用RSA非对称加密算法（SHA1withRSA），计算出最后的签名sign，对其base64编码，放入head的key（sign）中。
// func getSignature(bizData string, appId string, privateKeyPEM string) (signatureBase64 string, timestamp string, err error) {
// 	timestamp = strconv.FormatInt(time.Now().UnixMilli(), 10)

// 	privateKeyBlock, _ := pem.Decode([]byte(privateKeyPEM))
// 	// if privateKeyBlock == nil || privateKeyBlock.Type != "RSA PRIVATE KEY" {
// 	if privateKeyBlock == nil {
// 		err = errors.New("签名失败: Error decoding private key PEM")
// 		return
// 	}

// 	// 解析 PKCS#8 格式的私钥
// 	privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
// 	if err != nil {
// 		fmt.Println("Failed to parse private key:", err)
// 		return
// 	}

// 	// md5（bizData）
// 	m := md5.New()
// 	m.Write([]byte(bizData))
// 	bdMd5Hx := hex.EncodeToString(m.Sum(nil))

// 	// 待签内容
// 	message := bizData + bdMd5Hx + appId + timestamp

// 	// 使用私钥进行签名
// 	hashed := sha256.Sum256([]byte(message))
// 	signature, err := rsa.SignPKCS1v15(nil, privateKey, crypto.SHA256, hashed[:])
// 	if err != nil {
// 		fmt.Println("Error signing:", err)
// 		return
// 	}

// 	// fmt.Println(signature)
// 	signatureBase64 = base64.StdEncoding.EncodeToString(signature)

// 	return
// }

// type pySignReqData struct {
// 	ReqBodyData string `json:"reqBodyData"`
// 	Timestamp   string `json:"timestamp"`
// 	AppId       string `json:"appId"`
// 	AppKey      string `json:"appKey"`
// }

// func getSignatureByPy(bizData string, appId string, privateKeyPEM string) (signatureBase64 string, timestamp string, err error) {
// 	// md5（bizData）
// 	m := md5.New()
// 	m.Write([]byte(bizData))
// 	bdMd5Hx := hex.EncodeToString(m.Sum(nil))
// 	timestamp = strconv.FormatInt(time.Now().UnixMilli(), 10)
// 	// timestamp = "1691559290641"
// 	// 待签内容
// 	message := bizData + bdMd5Hx + appId + timestamp

// 	// 构建请求数据结构
// 	reqData := pySignReqData{
// 		ReqBodyData: message,
// 		Timestamp:   timestamp,
// 		AppId:       appId,
// 		AppKey:      privateKeyPEM,
// 	}
// 	// 将请求数据转换为JSON字符串
// 	reqJSON, err := json.Marshal(reqData)
// 	if err != nil {
// 		global.M2A_LOG.Error("[getSignatureByPy] 构建请求参数失败", zap.Error(err))
// 		return
// 	}
// 	// 要执行的Python脚本命令
// 	pythonScriptPath := "./py/sign.py"
// 	// 创建一个命令对象
// 	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
// 	// 设置标准输入为JSON字符串
// 	cmd.Stdin = strings.NewReader(string(reqJSON))
// 	// 获取标准输出
// 	output, err := cmd.CombinedOutput()
// 	if err != nil {
// 		global.M2A_LOG.Error("[getSignatureByPy] 签名失败", zap.Error(err))
// 		return
// 	}
// 	// 获取签名结果
// 	signatureBase64 = string(output)

// 	return
// }

type AsignData interface {
	AddPersonalUserData | CreateContractData | AddSignerData | DownloadContractData | ContractStatusData | WillFaceData
}

// AsignRsp 爱签响应参数
type AsignRsp[T AsignData] struct {
	Code int    `json:"code"` // 响应码，100000表示成功，其他表示异常
	Msg  string `json:"msg"`  // 响应信息
	Data T      `json:"data"` // 	响应数据
}

// https://preweb.asign.cn/platform/openDoc/docDetail?mid=addPersonalUser
// 添加个人用户(https://{host}/user/addPersonalUser)
// 错误码	错误描述
// 100021	用户已存在
// 100156	手机号码格式错误
// 100157	邮箱格式错误
// 100571	参数错误，唯一识别码Account为空
// 100577	参数错误，{param}长度超过限制:{length}
// 100579	参数错误，{param}不能为空
// 100598	参数错误，身份证号码格式不正确
// 100639	参数错误，名字点号格式不正确
// func AddPersonalUser(account, name, idCard, mobile string, idCardType *int) (rspData AddPersonalUserRsp, err error) {
// 	apiUrl := global.M2A_CONFIG.Asign.URL + "user/addPersonalUser"
// 	appId := "290912417"
// 	privateKey := `MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAkMD+72J6iAF0ZNV+3t628lsRHfJ80nKZWK5/C7Pg+AZmOIzJlwHsKhRzCvxoxqYHQprhiFzW9l73v9vD9l1JYwIDAQABAkBVijccr01JYdKuY5t9iI8D2NzcnZc1pZMI3NUmzT18Uyg7b9CUvGHlLeg/gdT4QtVd7wIzHYCY4letEcEMh54BAiEAwzNWusj5XiLmty7PI0Hbakx4HtcND1+P0UHLEWqWOuECIQC91zQuL7nStgGzT3HvaeBB5Ouapa39fHRm2nCjHaxwwwIgRR2XdvmUOj23XWMomr5F14SN/7V7fVcD0D8wjNElsmECIDYavV5kb7tj7/wgqkInlKhzC8rZaUsTS0F9BBkY/eptAiAQJ8Saz8YlMIESdHMxANGSog01fECbcZqLFMuNf8SorA==`

// 	// 请求参数
// 	params := make(map[string]interface{})
// 	params["account"] = account
// 	params["name"] = name
// 	params["idCard"] = idCard
// 	params["idCardType"] = 1
// 	if idCardType != nil {
// 		params["idCardType"] = *idCardType
// 	}
// 	params["mobile"] = mobile
// 	// 用户实名认证模式为强制认证时，需要选择认证方法：
// 	// 1：身份证二要素认证
// 	// 2：运营商三要素认证
// 	// 3：银行卡四要素认证
// 	params["identifyType"] = 2
// 	params["identifyMobile"] = mobile
// 	params["isNotice"] = 1
// 	bizData, err := json.Marshal(params)
// 	if err != nil {
// 		global.M2A_LOG.Error("[AddPersonalUser] 构建请求参数失败", zap.Error(err))
// 		return
// 	}
// 	global.M2A_LOG.Info("[AddPersonalUser] 构建请求参数", zap.Any("params", string(bizData)))
// 	// 签名
// 	sign, timestamp, err := getSignatureByPy(string(bizData), appId, privateKey)
// 	sign = strings.Replace(sign, "\r\n", "", -1)
// 	sign = strings.Replace(sign, "\r", "", -1)
// 	if err != nil {
// 		global.M2A_LOG.Error("[AddPersonalUser] 签名失败", zap.Error(err))
// 		return
// 	}
// 	global.M2A_LOG.Info("[AddPersonalUser] 签名", zap.Any("sign", sign))
// 	// 构建form-data请求参数
// 	formValues := url.Values{}
// 	formValues.Set("appId", appId)
// 	formValues.Set("timestamp", timestamp)
// 	formValues.Set("bizData", string(bizData))
// 	// 构建请求
// 	req, err := http.NewRequest("POST", apiUrl, bytes.NewReader([]byte(formValues.Encode())))
// 	// 设置请求头
// 	req.Header.Set("sign", sign)
// 	req.Header.Set("timestamp", timestamp)
// 	req.Header.Set("Content-Type", "multipart/form-data; charset=UTF-8")
// 	req.Header.Set("Accept", "*/*")

// 	client := &http.Client{}
// 	rsp, err := client.Do(req)
// 	if err != nil {
// 		global.M2A_LOG.Error("[AddPersonalUser] 请求失败", zap.Error(err))
// 		return
// 	}
// 	defer rsp.Body.Close()
// 	body, err := io.ReadAll(rsp.Body)
// 	if err != nil {
// 		global.M2A_LOG.Error("[AddPersonalUser] 获取body失败", zap.Error(err))
// 		return
// 	}
// 	if err = json.Unmarshal(body, &rspData); err != nil {
// 		global.M2A_LOG.Error("[AddPersonalUser] 反序列化body失败", zap.Error(err))
// 		return
// 	}

// 	return
// }

type AddPersonalUserData struct {
	SealNo string `json:"sealNo"` // 默认印章编号
}

// https://preweb.asign.cn/platform/openDoc/docDetail?mid=addPersonalUser
// 添加个人用户(https://{host}/user/addPersonalUser)
// 错误码	错误描述
// 100021	用户已存在
// 100156	手机号码格式错误
// 100157	邮箱格式错误
// 100571	参数错误，唯一识别码Account为空
// 100577	参数错误，{param}长度超过限制:{length}
// 100579	参数错误，{param}不能为空
// 100598	参数错误，身份证号码格式不正确
// 100639	参数错误，名字点号格式不正确
func AddPersonalUserBy(account, name, idCard, mobile string, idCardType *int) (rspData AsignRsp[AddPersonalUserData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "user/addPersonalUser"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["account"] = account
	reqData["name"] = name
	reqData["mobile"] = mobile
	reqData["idCard"] = idCard
	reqData["idCardType"] = 1
	if idCardType != nil {
		reqData["idCardType"] = *idCardType
	}

	reqData["api"] = "addPerson"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[AddPersonalUserBy] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	global.M2A_LOG.Info("AddPersonalUserBy 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("AddPersonalUserBy 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[AddPersonalUserBy] 请求失败", zap.Error(err))
		return
	}
	// 结果
	rspBody := stdoutBuf.String()
	// 正确返回
	// {"code":100000,"msg":"�ɹ�","data":{"id":null,"userId":null,"partnerId":null,"type":null,"sealType":null,"sealTypeOfUser":null,"sealName":null,"sealCode":null,"startTime":null,"endTime":null,"sealNo":"9a82d2da479b4430b1da6f7f7cd96aee","sealPassword":null,"sealFont":null,"version":null,"caType":null,"certNo":null,"path":null,"isDefault":null,"status":null,"color":null,"fontSize":null,"imageWidth":null,"imageHeight":null,"imageShape":null,"signTimes":null,"logicDel":null,"createTime":null,"modifyTime":null}}
	// 错误返回
	// {"code":100021,"msg":"�û��Ѵ��ڣ�����֤�����ظ�","data":{"id":null,"partnerId":null,"account":"100000007","companyAccount":null,"name":null,"companyName":null,"userType":null,"mobile":null,"bankCard":null,"email":null,"idCard":"360428200007287603","idCardType":null,"creditCode":null,"contactName":null,"contactPhone":null,"contactIdCard":null,"isNotice":null,"isAutoSign":null,"signPwd":null,"identifyStatus":null,"identifyMobile":null,"identifyType":null,"userStatus":null,"needSeal":null,"remark":null,"createTime":null,"modifyTime":null,"sealType":null,"authType":null,"serialNo":null}}
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[AddPersonalUserBy] 反序列化body失败", zap.Error(err))
		return
	}

	return
}

type CreateContractData struct {
	PreviewUrl    string        `json:"previewUrl"`    // 合同预览链接
	ContractFiles []interface{} `json:"contractFiles"` // 合同文件信息（文件名称，附件编号，页数）
}

/*
*
CreateContract 上传待签署文件

contractNo 合同ID，合同唯一编号
contractName 合同名称
templateNo 合同模板编号
*
*/
func CreateContract(contractNo, contractName, templateNo string) (rspData AsignRsp[CreateContractData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "contract/createContract"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["contractNo"] = contractNo
	reqData["contractName"] = contractName
	reqData["validityTime"] = 30
	reqData["signOrder"] = 1 // 1：无序签约（默认
	reqData["templates"] = []map[string]string{
		{"templateNo": templateNo}} // 合同模板编号 - 目前只支持一份合同签一份协议
	reqData["notifyUrl"] = global.M2A_CONFIG.Asign.NotifyUrl

	reqData["api"] = "createContract"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[CreateContract] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	// fmt.Println("标准输入:", string(reqJSON))
	global.M2A_LOG.Info("CreateContract 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("CreateContract 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[CreateContract] 请求失败", zap.Error(err))
		return
	}
	// 结果
	rspBody := stdoutBuf.String()
	// 正确返回：CreateContract 标准输出: {"code":100000,"msg":" ɹ ","data":{"pageSizeMap":{},"signUser":[],"previewUrl":"https://pre.asign.cn/m/#/mobile/previewApiContract/QhUqHj669cOmXIPrJ7eOhSfWh6_oDGlmQ53lOD5OVAvJRvTVpenYICiMWnvbCi4swvNWUIVuO1zPsTvIvHPGuE1fTZ-AQyCeUyWWu7f56Jg?expired=10800000","contractFiles":[]}}
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[CreateContract] 反序列化body失败", zap.Error(err))
		return
	}

	return
}

// 合同用户信息
type SignUserData struct {
	Account    string `json:"account"`    // 用户唯一识别码
	SignUrl    string `json:"signUrl"`    // 合同签署链接
	PwdSignUrl string `json:"pwdSignUrl"` // 密码签署链接
	SignOrder  int    `json:"signOrder"`  // 顺序签约的序号
	Name       string `json:"name"`       // 用户姓名
	IdCard     string `json:"idCard"`     // 	用户身份证
}

// 添加签署方响应数据
type AddSignerData struct {
	ContractNo   string         `json:"contractNo"`   // 合同编号
	ContractName string         `json:"contractName"` // 合同名称
	ValidityTime string         `json:"validityTime"` // 合同有效期
	PreviewUrl   string         `json:"previewUrl"`   // 合同预览链接
	SignUser     []SignUserData `json:"signUser"`     // 合同用户信息
}

/*
*
AddSigner 添加签署方

contractNo 合同ID，合同唯一编号
account 用户唯一识别码（UserID）
*
*/
func AddSigner(contractNo, account string) (rspData AsignRsp[AddSignerData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "contract/addSigner"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["contractNo"] = contractNo
	reqData["account"] = account
	reqData["signType"] = 3
	// 签署方式指定：（从以下分类中指定一种）
	// 1：短信验证码签约（支持企业和个人）
	// 2：签约密码签约（支持企业和个人）
	// 3：人脸识别签约（支持企业和个人）
	// 4：手写签名（不推荐，仅限个人）
	// 6：手写识别签名+短信签约（仅限个人）
	// 7：手写签名+短信签约（仅限个人）
	// 8：手写签名+人脸识别签约（仅限个人）
	// 9：手写识别签名+人脸识别签约（仅限个人）
	reqData["validateType"] = 4
	reqData["signStrategyList"] = []map[string]interface{}{
		{"attachNo": 1, "locationMode": 4, "signKey": "key_sign_name"},
		{"attachNo": 1, "locationMode": 4, "signKey": "key_sign_date"},
	}

	reqData["api"] = "addSigner"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[AddSigner] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	global.M2A_LOG.Info("AddSigner 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("AddSigner 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[AddSigner] 请求失败", zap.Error(err))
		return
	}
	// 结果
	// 正确返回：AddSigner 标准输出: {"code":100000,"msg":"�ɹ�","data":{"contractNo":"100000008_20230815145538_10","pageSizeMap":{},"contractName":"���ݲ�Ҷ������ʾ�飨10.31���հ棩","signOrder":1,"validityTime":"2023-09-14","signUser":[{"account":"100000008","signUrl":"https://h5.asign.cn/web/short/eE7zmq515512","signOrder":1,"name":"����̼��","idCard":"110101200007285605","mobile":"15914012153"}],"previewUrl":"https://pre.asign.cn/m/#/mobile/previewApiContract/QhUqHj669cOmXIPrJ7eOhSfWh6_oDGlmQ53lOD5OVAvJRvTVpenYICiMWnvbCi4sS_knh8JQ124Lwf_uxqXkF0-n1uuC18qLy5B8TfAF88g?expired=10800000","contractFiles":[]}}
	// 错误返回：AddSigner 标准输出: {"code":100617,"msg":"ģ  Ĳ       [key_sign_name]      ","data":null}
	rspBody := stdoutBuf.String()
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[AddSigner] 反序列化body失败", zap.Error(err))
		return
	}

	return
}

// 下载合同响应数据
type DownloadContractData struct {
	FileName string `json:"fileName"` // 文件名
	MD5      string `json:"md5"`      // 文件md5值
	FileType int    `json:"fileType"` // 文件类型 0：PDF 1：ZIP
	Size     int    `json:"size"`     // 文件大小
	Data     string `json:"data"`     // Base64字符串
}

/*
DownloadContract 下载合同

contractNo 合同ID，合同唯一编号
*/
func DownloadContract(contractNo string) (rspData AsignRsp[DownloadContractData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "contract/downloadContract"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["contractNo"] = contractNo

	reqData["api"] = "downloadContract"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[DownloadContract] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	global.M2A_LOG.Info("DownloadContract 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("DownloadContract 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[DownloadContract] 请求失败", zap.Error(err))
		return
	}
	// 结果
	rspBody := stdoutBuf.String()
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[DownloadContract] 反序列化body失败", zap.Error(err))
		return
	}

	return
}

// 查询合同状态响应数据
type ContractStatusData struct {
	ContractNo   string `json:"contractNo"`   // 合同唯一编号
	ContractName string `json:"contractName"` // 合同名称
	Status       int    `json:"status"`       // 合同状态：0：等待签约 1：签约中 2：已签约 3：过期 4：拒签 6：作废 -2：状态异常
}

/*
ContractStatus 查询合同状态

contractNo 合同ID，合同唯一编号
*/
func ContractStatus(contractNo string) (rspData AsignRsp[ContractStatusData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "contract/status"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["contractNo"] = contractNo

	reqData["api"] = "contractStatus"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[ContractStatus] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	global.M2A_LOG.Info("ContractStatus 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("ContractStatus 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[ContractStatus] 请求失败", zap.Error(err))
		return
	}
	// 结果
	rspBody := stdoutBuf.String()
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[ContractStatus] 反序列化body失败", zap.Error(err))
		return
	}

	return
}

// 个人意愿核身认证响应数据
type WillFaceData struct {
	Result   int    `json:"result"`   // 认证结果：0.暂无结果/认证中
	SerialNo string `json:"serialNo"` // 认证流水号
	Type     string `json:"type"`     // 认证类型
	FaceUrl  string `json:"faceUrl"`  // 意愿核身链接
}

/*
WillFace 个人意愿核身认证
*/
func WillFace(realName, idCardNo, question, answer, recordId string) (rspData AsignRsp[WillFaceData], err error) {
	apiUrl := global.M2A_CONFIG.Asign.URL + "auth/person/willFace"

	// 构建请求数据结构
	reqData := make(map[string]interface{})
	reqData["realName"] = realName
	reqData["idCardNo"] = idCardNo
	reqData["question"] = question
	reqData["answer"] = answer
	reqData["redirectUrl"] = global.M2A_CONFIG.Asign.WillFaceRedirectUrl + "?recordId=" + recordId

	reqData["api"] = "willFace"
	reqData["appId"] = global.M2A_CONFIG.Asign.AppId
	reqData["appKey"] = global.M2A_CONFIG.Asign.PrivateKey
	reqData["apiUrl"] = apiUrl

	// 将请求数据转换为JSON字符串
	reqJSON, err := json.Marshal(reqData)
	if err != nil {
		global.M2A_LOG.Error("[WillFace] 构建请求参数失败", zap.Error(err))
		return
	}
	// 要执行的Python脚本命令
	pythonScriptPath := "./py/Enter.py"
	// 创建一个命令对象
	cmd := exec.Command(global.M2A_CONFIG.Asign.Py, pythonScriptPath)
	// 设置标准输入为JSON字符串
	cmd.Stdin = strings.NewReader(string(reqJSON))
	// 创建一个字节缓冲区来捕获命令的输出
	var stdoutBuf, stderrBuf bytes.Buffer
	cmd.Stdout = &stdoutBuf
	cmd.Stderr = &stderrBuf
	// 执行命令
	err = cmd.Run()
	// 输出标准输出和标准错误
	global.M2A_LOG.Info("WillFace 标准输出:", zap.Any("stdoutBuf", stdoutBuf.String()))
	global.M2A_LOG.Info("WillFace 标准错误:", zap.Any("stderrBuf", stderrBuf.String()))
	if err != nil {
		global.M2A_LOG.Error("[WillFace] 请求失败", zap.Error(err))
		return
	}
	// 结果
	rspBody := stdoutBuf.String()
	if err = json.Unmarshal([]byte(rspBody), &rspData); err != nil {
		global.M2A_LOG.Error("[WillFace] 反序列化body失败", zap.Error(err))
		return
	}

	return
}
