package zoho

import (
	"crm-api/internal/app/mysql"
	"crm-api/pkg/httpclient"
	"crm-api/pkg/lfshook"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"slices"
	"strconv"
	"strings"
	"time"

	"gopkg.in/ini.v1"
)

var TimestampList = make(map[string]string)    //临时记录通话成功时的初始时间戳，用于计算通话时长，通话结束后删除
var StartTimeList = make(map[string]time.Time) //临时记录通话的初始时间，通话结束时删除
// var LinkedidList = make(map[string]string)     // 临时记录 incoming 和 outgoing
// var DialStatusList = make(map[string]string) // 临时记录 DialStatus:ANSWER NOANSWER
var CallTypeList = make(map[string]string)               //通过Linkedid临时记录拨打类型呼入还是呼出，通话结束后删除
var TimetimesList = make(map[string]int)                 //通过Linkedid临时记录呼入队列或部门的数量，通话结束后删除
var AttendedTransferList = make(map[string]string)       //临时记录协商转接的初始时间戳
var AttendedSecondTransferList = make(map[string]string) //临时记录协商转接后的初始时间戳
var ZohoExtenList = make([]string, 0)                    //记录zoho用户分机列表，只有zoho用户分机的呼入和呼出才会进行推送
var n int                                                //临时记录判断通话未接听的数量，若与呼入数量相同进行推送，若接听让n归0
var ZOHO_URL string                                      //设置推送地址
// macro-trunkdial-failover为呼出判定；macro-stdexten为呼入开启语音留言的判定；macro-stdexten-withoutvm为呼入关闭语音留言的判定
func CallClicktodialerror(event map[string]string) {
	//CallClicktodialerrorh函数用于过滤zoho crm拨打时出现的错误
	if event["Event"] == "SoftHangupRequest" {
		Channel := strings.Split(event["Channel"], "/")
		if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && len(event["Exten"]) > 3 && Channel[0] == "Local" {
			ExtenStatus := strings.Split(event["Exten"], "-")

			if ExtenStatus[1] == "NOANSWER" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) { //坐席未接听，通过ExtenStatus判断挂断原因，slices.Contains(ZohoExtenList, event["ConnectedLineNum"])判断主叫是否时zoho用户分机（坐席）
				getURL := fmt.Sprintf("%s/phonebridge/v3/clicktodialerror?code=noanswer&from=%s&to=%s", ZOHO_URL, event["ConnectedLineNum"], event["CallerIDNum"])

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
				return
			} else if ExtenStatus[1] == "BUSY" { //坐席不可用
				ChannelStatus1 := strings.Split(event["Channel"], "@")
				ChannelStatus2 := strings.Split(ChannelStatus1[0], "/")
				if slices.Contains(ZohoExtenList, ChannelStatus2[1]) {
					getURL := fmt.Sprintf("%s/phonebridge/v3/clicktodialerror?code=notavailble&from=%s&to=%s&message=agentunavailable", ZOHO_URL, ChannelStatus2[1], event["CallerIDNum"])

					// fmt.Println("getURL = ", getURL)
					go httpclient.ZohoGet(getURL)
					return
				}

			} else if ExtenStatus[1] == "CHANUNAVAIL" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) { //坐席拒接
				getURL := fmt.Sprintf("%s/phonebridge/v3/clicktodialerror?code=rejected&from=%s&to=%s", ZOHO_URL, event["ConnectedLineNum"], event["CallerIDNum"])

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
				return
			}
		}
	} else if event["Event"] == "DialEnd" { //坐席未接听
		Channel := strings.Split(event["Channel"], "/")
		if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && event["DialStatus"] == "CANCEL" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) && Channel[0] == "Local" {
			getURL := fmt.Sprintf("%s/phonebridge/v3/clicktodialerror?code=noanswer&from=%s&to=%s", ZOHO_URL, event["ConnectedLineNum"], event["CallerIDNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			return
		}
	}

	CallNotify(event)

}
func CallNotify(event map[string]string) {

	// 坐席接听后调用此函数
	if event["Event"] == "DialBegin" { //响铃标志事件
		lfshook.NewLogger().Error(event)

		Channel := strings.Split(event["Channel"], "/")

		// Outgoing Call - Ringing
		if event["Context"] == "macro-trunkdial-failover" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) {
			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=ringing&id=10031&from=123456789&to=12300000001
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)

			// Incoming Call - Ringing
		} else if (event["Context"] == "macro-stdexten" && Channel[0] != "Local" && slices.Contains(ZohoExtenList, event["DestCallerIDNum"])) || (event["Context"] == "macro-stdexten-withoutvm" && Channel[0] != "Local" && slices.Contains(ZohoExtenList, event["DestCallerIDNum"])) { // 开启语音留言:macro-stdexten  关闭语音留言:macro-stdexten-withoutvm

			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=ringing&id=10033&from=12300000001&to=123456789
			// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["Exten"], callDest) // 取得from to 可能不准
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)

		} else if (strings.HasPrefix(event["Context"], "department") || strings.HasSuffix(event["Context"], "queue")) && slices.Contains(ZohoExtenList, event["DestCallerIDNum"]) { //队列和部门判断
			TimetimesList[event["Linkedid"]] = TimetimesList[event["Linkedid"]] + 1
			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
		}

	} else if event["Event"] == "DialEnd" { // 呼叫结束事件,未接听集合
		Channel := strings.Split(event["Channel"], "/")
		// 记录呼叫状态
		// Outgoing Call - Unattended
		if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "CANCEL" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) { //坐席取消呼叫客户电话,event["DialStatus"]判断未接听挂断原因

			// startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=busy&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			delete(StartTimeList, event["Linkedid"])
			// Incoming Call - Missed
		} else if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "NOANSWER" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) { //坐席呼出，客户未接听,event["DialStatus"]判断未接听挂断原因

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=noanswer&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			delete(StartTimeList, event["Linkedid"])
			// Incoming Call - Missed
		} else if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "BUSY" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) { //坐席呼出，客户拒接

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=rejected&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			delete(StartTimeList, event["Linkedid"])
			// Incoming Call - Missed
		} else if (event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" && Channel[0] != "Local" && slices.Contains(ZohoExtenList, event["DestCallerIDNum"])) || (event["Context"] == "macro-stdexten-withoutvm" && event["DialStatus"] != "ANSWER" && Channel[0] != "Local" && slices.Contains(ZohoExtenList, event["DestCallerIDNum"])) { // 呼入坐席未接听

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=missed&id=10005&from=12300000001&to=123456789&start_time=2024-12-04 15:09:10
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)
			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			delete(StartTimeList, event["Linkedid"])
		} else if (strings.HasPrefix(event["Context"], "department") || strings.HasSuffix(event["Context"], "queue")) && event["DialStatus"] != "ANSWER" && TimetimesList[event["Linkedid"]] < 2 && TimetimesList[event["Linkedid"]] > 0 && slices.Contains(ZohoExtenList, event["DestCallerIDNum"]) { //呼入队列或部门成员未接听（一个）

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)
			delete(TimetimesList, event["Linkedid"])
			delete(StartTimeList, event["Linkedid"])
		} else if (strings.HasPrefix(event["Context"], "department") || strings.HasSuffix(event["Context"], "queue")) && event["DialStatus"] != "ANSWER" && TimetimesList[event["Linkedid"]] >= 2 && slices.Contains(ZohoExtenList, event["DestCallerIDNum"]) { //呼入队列或部门（两个以上）

			n = n + 1
			if TimetimesList[event["Linkedid"]] == n {
				startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
				startTime := startTimeutc.Format(time.RFC3339)
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
				delete(TimetimesList, event["Linkedid"])
				delete(StartTimeList, event["Linkedid"])
				n = 0
			}

		} else if event["DialStatus"] == "ANSWER" {
			delete(TimetimesList, event["Linkedid"])
		}

		// 呼叫已连接事件
	} else if event["Event"] == "BridgeEnter" { //接听标志事件
		Channel := strings.Split(event["Channel"], "/")
		// Outgoing Call - Answered
		if event["Context"] == "macro-trunkdial-failover" && event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) { // 注意这里选择 Priority:1 的，便于确认 CallerIDNum，ConnectedLineNum
			// 记录开始时间
			TimestampList[event["Linkedid"]] = event["Timestamp"]
			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
			// LinkedidList["Linkedid"] = event["Linkedid"]
			CallTypeList[event["Linkedid"]] = "outgoing"
			// https: //www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=answered&id=10003&from=123456789&to=12300000001
			// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"])
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)

			// Incoming Call - Answered
		} else if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && Channel[0] != "Local" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) && event["SwapUniqueid"] == "" { // event["SwapUniqueid"]判断是否转移
			// 记录开始时间
			TimestampList[event["Linkedid"]] = event["Timestamp"]             // 呼入时设置 Uniqueid 不是 Linkedid
			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour) // 呼入时设置 Uniqueid 不是 Linkedid
			CallTypeList[event["Linkedid"]] = "incoming"
			// https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=answered&id=10023&from=12300000001&to=123456789
			getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"])

			// fmt.Println("getURL = ", getURL)
			go httpclient.ZohoGet(getURL)

		} else if (strings.HasPrefix(event["Context"], "department") && event["Priority"] == "1" && event["SwapUniqueid"] == "") || (strings.HasSuffix(event["Context"], "queue") && event["SwapUniqueid"] == "") { //部门或队列成员接听
			TimestampList[event["Linkedid"]] = event["Timestamp"]             // 呼入时设置 Uniqueid 不是 Linkedid
			StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour) // 呼入时设置 Uniqueid 不是 Linkedid
			// LinkedidList["Linkedid"] = event["Linkedid"]
			CallTypeList[event["Linkedid"]] = "incoming"
			if event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) {

				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"])

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			} else if slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) {
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"])

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			}
			delete(TimetimesList, event["Linkedid"])
			n = 0
		}
		// else if event["SwapUniqueid"] != "" {
		// 	CallTypeList[event["Linkedid"]] = "incoming"
		// }

		// 呼叫挂断事件
	} else if event["Event"] == "Hangup" { //接听挂断标志事件

		// * ===================================================================================== */
		// 判断呼叫状态，为 ANSWER 时才推送，否则见以上推送 Outgoing Call - Unattended 或 Incoming Call - Missed
		Channel := strings.Split(event["Channel"], "/")

		// lfshook.NewLogger().Errorf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa %+v", event["Context"])
		// fmt.Println("ChannelHangupRequest1 = ", DialStatusList[event["Linkedid"]])

		// Outgoing Call - Ended
		if event["Context"] == "macro-trunkdial-failover" && CallTypeList[event["Linkedid"]] == "outgoing" { //坐席呼出挂断
			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			durationTime := getDuration(event["Linkedid"], event["Timestamp"])

			if durationTime != -1 { //判断通话时长是否正常
				if event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) {
					// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dailed&state=ended&id=10030&from=123456789&to=12300000001&start_time=2024-12-04 11:32:15&duration=325
					// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
					getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)

					// fmt.Println("getURL = ", getURL)
					go httpclient.ZohoGet(getURL)
				} else if slices.Contains(ZohoExtenList, event["CallerIDNum"]) {
					// https://www.zohoapis.com/phonebridge/v3/callnotify?type=dailed&state=ended&id=10030&from=123456789&to=12300000001&start_time=2024-12-04 11:32:15&duration=325
					// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
					getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)

					// fmt.Println("getURL = ", getURL)
					go httpclient.ZohoGet(getURL)
				}
			}
			// 删除记录时间
			delete(StartTimeList, event["Linkedid"])
			delete(CallTypeList, event["Linkedid"])

		} else if Channel[0] != "Local" && CallTypeList[event["Linkedid"]] == "incoming" && AttendedTransferList[event["Linkedid"]] == "" { //坐席呼入挂断

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)

			durationTime := getDuration(event["Linkedid"], event["Timestamp"])
			if durationTime != -1 {
				if event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) {
					getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
					// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

					// fmt.Println("getURL = ", getURL)
					go httpclient.ZohoGet(getURL)
				} else if slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) {
					getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
					// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

					// fmt.Println("getURL = ", getURL)
					go httpclient.ZohoGet(getURL)
				}

			}
			delete(StartTimeList, event["Linkedid"])
			delete(CallTypeList, event["Linkedid"])

		} else if AttendedTransferList[event["Linkedid"]] != "" && CallTypeList[event["Linkedid"]] == "incoming" { //转接挂断

			startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			durationTime := getDuration(event["Linkedid"], event["Timestamp"])
			if event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) {
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
				// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			} else if slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) {
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
				// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			}
			AttendedSecondTransferList[event["Linkedid"]] = AttendedTransferList[event["Linkedid"]] //创建转移后通话的初始时间戳
			delete(StartTimeList, event["Linkedid"])
			delete(CallTypeList, event["Linkedid"])
			delete(AttendedTransferList, event["Linkedid"])

		} else if AttendedSecondTransferList[event["Linkedid"]] != "" { //转接挂断
			startTimeutc := StartTimeList[AttendedSecondTransferList[event["Linkedid"]]].In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			durationTime := getDuration(AttendedSecondTransferList[event["Linkedid"]], event["Timestamp"])

			if event["Priority"] == "1" && slices.Contains(ZohoExtenList, event["CallerIDNum"]) {
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, AttendedSecondTransferList[event["Linkedid"]], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
				// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			} else if slices.Contains(ZohoExtenList, event["ConnectedLineNum"]) {
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, AttendedSecondTransferList[event["Linkedid"]], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
				// getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			}
			delete(StartTimeList, AttendedSecondTransferList[event["Linkedid"]])
			delete(AttendedSecondTransferList, event["Linkedid"])

		}

	} else if event["Event"] == "AttendedTransfer" && slices.Contains(ZohoExtenList, event["TransfereeConnectedLineNum"]) { //热转接
		if event["Result"] == "Success" {

			AttendedTransferList[event["OrigTransfererLinkedid"]] = event["SecondTransfererLinkedid"]

			delete(CallTypeList, event["SecondTransfererLinkedid"])
		}
	} else if event["Event"] == "SoftHangupRequest" { //呼入离线坐席
		Channel := strings.Split(event["Channel"], "/")
		if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && Channel[0] != "Local" && len(event["Exten"]) > 3 {
			startTimebj := time.Now().Add(-8 * time.Hour)
			startTimeutc := startTimebj.In(time.UTC) // 存储从string 改为 time.Time
			startTime := startTimeutc.Format(time.RFC3339)
			if event["ConnectedLineNum"] == "<unknown>" {
				ConnectedLineNum := strings.Split(strings.Split(event["ConnectedLineNum"], "<")[1], ">")[0]
				getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], ConnectedLineNum, startTime)

				// fmt.Println("getURL = ", getURL)
				go httpclient.ZohoGet(getURL)
			}

		}
	}

	// 测试验证下上面有没有删除，以防TimestampList越来越大
	// for k, v := range TimestampList {
	// 	fmt.Printf("===Linkedid:%s   Timestamp:%s===\n", k, v)
	// }

}

// 使用事件中event["Timestamp"]的值计算时间间隔
// func getDuration(uniqueid string, timeStamp string) int {
func getDuration(linkedid string, timeStamp string) int { // 都改为 Linkedid

	fmt.Println("startTimeStamp Str: ", TimestampList[linkedid])
	if TimestampList[linkedid] == "" || timeStamp == "" {
		fmt.Printf("linkedid 或 timeStamp 为空\n")
		return -1
	}

	startTimeStamp, err := strconv.ParseFloat(TimestampList[linkedid], 64)
	if err != nil {
		fmt.Printf("startTimeStamp转换出错: %v\n", err)
		return -1
	}
	fmt.Printf("startTimeStamp=%f\n", startTimeStamp)

	endTimeStamp, err := strconv.ParseFloat(timeStamp, 64)
	if err != nil {
		fmt.Printf("endTimeStamp转换出错: %v\n", err)
		return -1
	}
	fmt.Printf("endTimeStamp=%f\n", endTimeStamp)

	durationTime := time.Duration(endTimeStamp-startTimeStamp) * time.Second

	fmt.Printf("durationTime=%d\n", int(durationTime.Seconds())) // durationTime=35

	// 删除记录时间
	delete(TimestampList, linkedid)

	// return durationTime
	return int(durationTime.Seconds())
}

// @tags PBX-zoho
// @Summary 刷新token
// @Description 刷新token
// @Security ZohoToken
// @Accept  json
// @Produce  json
// @Router /api/zoho/refresh-token [post]
func RefreshToken() {

	// 获取配置文件信息
	// confPath := "/etc/asterisk/vtiger_api.conf"
	confPath := "/etc/asterisk/crm_api.conf"
	cfg, err := ini.Load(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	ZohoAuthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
	ZohoRefreshToken := cfg.Section("general").Key("zohoRefreshToken").String()
	ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
	ZohoClientSecret := cfg.Section("general").Key("zohoClientSecret").String()
	if ZohoAuthUrl == "" || ZohoRefreshToken == "" || ZohoClientId == "" || ZohoClientSecret == "" {
		lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoRefreshToken or zohoClientId or zohoClientSecret")
		return
	}

	// 创建请求
	// https://accounts.zoho.com/oauth/v2/token?refresh_token=1004.86c8c0e3db7bfe9133598825bef28eb9.17a82a3bf3e675c504f478c1b0b5c456
	// &client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV&client_secret=fc3aef43dc58af8a49d3ed597710924200b03f74d0&grant_type=refresh_token
	getURL := fmt.Sprintf("%s/oauth/v2/token?refresh_token=%s&client_id=%s&client_secret=%s&grant_type=refresh_token", ZohoAuthUrl, ZohoRefreshToken, ZohoClientId, ZohoClientSecret)
	fmt.Printf("getURL = %s\n", getURL)
	// data := httpRequest(ctx, "POST", getURL)
	// /* =====================================================================================
	req, err := http.NewRequest("POST", getURL, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return
	}

	// 创建HTTP客户端
	client := &http.Client{}

	// req.Header.Set("Authorization", "Bearer "+accessToken) // 刷新token时不需要

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		// api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}
	lfshook.NewLogger().Infof("data %+v", string(data))
	// * ===================================================================================== */
	refreshTokenData := RefreshTokenResp{}
	err = json.Unmarshal([]byte(data), &refreshTokenData)
	if err != nil {
		// 转换数据错误
		lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
		// api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 将获取的 access_token 写入文件 crm_api.conf
	cfg.Section("general").Key("zohoAccessToken").SetValue(refreshTokenData.AccessToken)
	ZOHO_URL = refreshTokenData.ApiDomain
	err = cfg.SaveTo(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		// api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))

}

// 每隔55分钟刷新token
func RefreshTokenTicker() {

	ticker := time.NewTicker(55 * time.Minute)
	defer ticker.Stop()
	done := make(chan bool)
	// go func() { // 注释掉OK
	for {
		select {
		case <-done:
			return
		case t := <-ticker.C:
			fmt.Println("Tick at", t)
			RefreshToken()
		}
	}
	// }()
}

// 每隔30秒更新zoho用户分机集合
func ZohoUserExtenList() {
	// 构建参数
	// lfshook.NewLogger().Error("来了")
	list := make([]string, 0)
	session := mysql.DBOrmInstance.Prepare()

	// 查询数据
	var data []TabZohouser
	_, err := session.FindAndCount(&data)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	for _, v := range data {
		// lfshook.NewLogger().Errorf("11111111111111111 %+v", v)
		if v.Exten != "" {
			// lfshook.NewLogger().Errorf("222222222222222 %+v", v)
			list = append(list, v.Exten)
		}

	}
	ZohoExtenList = list

	// lfshook.NewLogger().Error(ZohoExtenList)
}

func RefreshZohoUserExtenListTicker() {

	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()
	done := make(chan bool)
	// go func() { // 注释掉OK
	for {
		select {
		case <-done:
			return
		case <-ticker.C:
			// fmt.Println("Tick at", t)
			ZohoUserExtenList()
		}
	}
}
