package core

import (
	"bytes"
	"fmt"
	"github.com/goWxHook/goWxHook/utils/json"
	"io"
	"log/slog"
	"net/http"
	"time"
)

const (
	MtDebugLog                            = 11024 //  debug消息
	loginSuccessMsg                       = 11025 // 登录成功
	MtUserLogin                           = 11025 //  登录消息
	MtUserLogout                          = 11026 //  注销消息
	MtSqlQuery                            = 11027 //  数据库查询消息
	MtDataOwnerMsg                        = 11028 //  获取我的信息消息
	MtDataWxidMsg                         = 11029 //  获取单个好友信息
	MtDataFriendsMsg                      = 11030 //  获取好友列表消息
	MtDataChatroomsMsg                    = 11031 //  获取群聊列表消息
	MtDataChatroomMembersMsg              = 11032 //  获取群成员消息
	MtDataPublicsMsg                      = 11033 //  获取公众号消息
	MtUpdateWxidMsg                       = 11034 //  从网络更新单个好友信息消息
	MtUpdateRoomMemberMsg                 = 11035 //  从网络更新群成员信息消息
	MtSendTextmsg                         = 11036 //  发送文本消息
	MtSendChatroomAtmsg                   = 11037 //  发送群@消息
	MtSendCardmsg                         = 11038 //  发送名片消息
	MtSendLinkmsg                         = 11039 //  发送链接消息
	MtSendImgmsg                          = 11040 //  发送图片消息
	MtSendFilemsg                         = 11041 //  发送文件消息
	MtSendVideomsg                        = 11042 //  发送视频消息
	MtSendGifmsg                          = 11043 //  发送gif消息
	MtRecvTextMsg                         = 11046 //  接收文本消息
	MtRecvPictureMsg                      = 11047 //  接收图片消息
	MtRecvVoiceMsg                        = 11048 //  接收视频消息
	MtRecvFriendMsg                       = 11049 //  接收申请好友消息
	MtRecvCardMsg                         = 11050 //  接收名片消息
	MtRecvVideoMsg                        = 11051 //  接收视频消息
	MtRecvEmojiMsg                        = 11052 //  接收表情消息
	MtRecvLocationMsg                     = 11053 //  接收位置消息
	MtRecvLinkMsg                         = 11054 //  接收链接消息
	MtRecvFileMsg                         = 11055 //  接收文件消息
	MtRecvMiniappMsg                      = 11056 //  接收小程序消息
	MtRecvWcpayMsg                        = 11057 //  接收好友转账消息
	MtRecvSystemMsg                       = 11058 //  接收系统消息
	MtRecvRevokeMsg                       = 11059 //  接收撤回消息
	MtRecvOtherMsg                        = 11060 //  接收其他未知消息
	MtRecvOtherAppMsg                     = 11061 //  接收应用类型未知消息
	MtAddFriendMsg                        = 11062 //  发送加好友消息
	MtModFriendRemarkMsg                  = 11063 //  发送修改好友备注消息
	MtDelFriendMsg                        = 11064 //  发送删除好友消息
	MtAcceptFriendMsg                     = 11065 //  发送同意加好友申请消息
	MtAcceptWcpayMsg                      = 11066 //  发送接收好友转帐消息
	MtAcceptRoomMsg                       = 11067 //  发送同意进群邀请消息
	MtCreateRoomMsg                       = 11068 //  发送创建群聊消息
	MtInviteToRoomMsg                     = 11069 //  发送邀请好友进群消息，40人以下
	MtInviteToRoomReqMsg                  = 11070 //  发送邀请好友进群消息，40人以上
	MtDelRoomMemberMsg                    = 11071 //  发送删除群成员消息
	MtModRoomNameMsg                      = 11072 //  发送修改群名称消息
	MtModRoomNoticeMsg                    = 11073 //  发送修改群通知消息
	MtModRoomMemberNameMsg                = 11074 //  发送修改我在本群的昵称消息
	MtModRoomShowNameMsg                  = 11075 //  发送修改显示群昵称消息
	MtSaveRoomToContactMsg                = 11076 //  发送保存到联系人消息
	MtQuitDelRoomMsg                      = 11077 //  发送退出并删除群消息
	MtModRecvNotifyMsg                    = 11078 //  发送消息免打扰消息
	MtModChatSessionTopMsg                = 11079 //  发送置顶消息
	MtZombieCheckMsg                      = 11080 //  发送无痕清粉消息
	MtAutoAcceptFriendMsg                 = 11081 //  发送自动同意好友申请消息
	MtAutoAcceptWcpayMsg                  = 11082 //  发送自动同意好友转帐消息
	MtAutoAcceptRoomMsg                   = 11083 //  发送自动进群邀请消息
	MtAutoAcceptCardMsg                   = 11084 //  发送自动加名片消息
	MtDecryptImgMsg                       = 11085 //  发送解密图片消息
	MtOpenBrowserMsg                      = 11086 //  发送打开浏览器消息
	MtRefreshLoginQrcode                  = 11087 // 刷新登录二维码
	MtSwitchSessionMsg                    = 11090 //  发送切换当前会话消息
	MtSearchWxUserMsg                     = 11096 // 搜索微信用户
	MtAddSearchUserMsg                    = 11097 // 添加搜索的微信用户
	MtVoiceToTextMsg                      = 11112 // 语音消息转文本（旧）
	MtSendXmlMsg                          = 11113 // 发送XML原始消息
	MtLogoutMsg                           = 11104 //  发送注销登录消息
	MtExitMsg                             = 11105 //  发送退出微信消息
	MtClearChatRecordMsg                  = 11108 //  清除聊天记录
	MtGetCollectListMsg                   = 11109 //  获取收藏列表
	MtSendCollectMsg                      = 11110 // 发送收藏（旧）
	MtSendCollectMsgByMsgId               = 11111 // 收藏指定消息(旧)
	MtGetWorkWxChatRoomMsg                = 11129 // 获取企业微信群
	MtGetWorkWxChatRoomMemberMsg          = 11130 //获取企业微信群成员
	MtGetWorkWxUserListMsg                = 11132 //  获取企业微信好友
	MtGetChatRoomInviteRelationMsg        = 11134 // 获取群成员邀请关系(协议)
	MtGetA8KeyMsg                         = 11135 // A8Key接口
	MtGetMiniProgramCodeMsg               = 11136 // 获取小程序授权code
	MtAddTagMsg                           = 11137 // 添加标签
	MtDeleteTagMsg                        = 11138 // 删除标签
	MtModifyTagMsg                        = 11139 // 修改标签
	MtAddTagToUserMsg                     = 11140 // 批量给用户加标签
	MtGetTagListByWxidMsg                 = 11141 // 获取指定好友的所有标签
	MtGetTagListMsg                       = 11142 // 获取标签列表
	MtGetMomentMsg                        = 11145 // 获取朋友圈
	MtCommentMomentMsg                    = 11146 // 朋友圈评论
	MtLikeMomentMsg                       = 11147 // 朋友圈点赞
	MtSendMomentMsg                       = 11148 // 朋友圈发表
	MtUploadMomentImageMsg                = 11149 // 朋友圈上传图片
	MtGetFriendMomentMsg                  = 11150 // 获取好友朋友圈
	MtVideoMomentInitMsg                  = 11160 // 视频号初始化
	MtVideoMomentSearchMsg                = 11161 // 视频号搜索
	MtLiveEnterMsg                        = 11162 //进入直播间
	MtLiveGetChangeInfoMsg                = 11163 // 获取直播间变动信息(人气，实时发言等)
	MtLiveSendMsg                         = 11164 // 发送直播间消息
	MtVideoMomentFollowMsg                = 11167 // 关注博主
	MtVideoMomentLikeMsg                  = 11168 // 视频号点赞
	MtVideoMomentVideoDetailMsg           = 11169 // 查看视频详细信息(包含评论)
	MtVideoMomentUserHomeMsg              = 11170 // 视频号用户主页
	MtLiveGetOnlineUserMsg                = 11172 // 获取直播间在线人员
	MtGetFriendDetailMsg                  = 11174 // 获取好友详细信息（协议）
	MtLiveGetShelfMsg                     = 11186 // 获取直播间货架
	MtVideoMomentCreateVirtualNickNameMsg = 11194 // 视频号创建虚拟昵称
	MtVideoMomentSwitchVirtualNickNameMsg = 11195 // 视频号切换虚拟昵称
	MtVideoMomentDeleteVirtualNickNameMsg = 11197 // 视频号删除虚拟昵称
	MtVideoMomentGetSessionIdMsg          = 11202 // 获取视频号私信sessionId
	MtVideoMomentSendMsg                  = 11203 // 发送视频号私信
	MtCdnSendXmlMsg                       = 11214 // 发送XML原始消息
	MtCdnInitialMsg                       = 11228 // CDN初始化
	MtCdnUploadFileMsg                    = 11229 // CDN上传
	MtCdnDownloadFileMsg                  = 11230 // CDN下载
	MtCdnSendImageMsg                     = 11231 // 发送图片消息
	MtCdnSendVideoMsg                     = 11233 // 发送视频消息
	MtCdnSendFileMsg                      = 11235 // 发送文件消息
	MtCdnSendCardLinkMsg                  = 11236 // 发送链接卡片消息
	MtCdnSendTextMsg                      = 11237 // 发送文本消息
	MtCdnSendLocationMsg                  = 11238 // 发送位置
	MtCdnSendCardMsg                      = 11239 // 发送名片
	MtCdnSendAtTextMsg                    = 11240 // 发送At消息
	MtCdnSendGifMsg                       = 11241 // 发送动图消息
	MtCdnSendMiniProgramMsg               = 11242 // 发送小程序
	MtCdnSendVideoMomentMsg               = 11243 // 发送视频号
	MtCdnSendRevokeMsg                    = 11244 // 撤回消息
	MtForwardMsg                          = 11245 // 转发任意类型消息
	MtCreateRoomByProtocolMsg             = 11246 // 创建群聊(协议)
	MtWorkWxCdnDownloadMsg                = 11253 // 企业微信CDN
	MtCdnSendGifMsgNew                    = 11254 // 发送动图消息New
)

type RespJson struct {
	Error int    `json:"error"`
	Msg   string `json:"msg"`
	Data  any    `json:"data"`
}

type WxApi struct {
	UserInfo UserClientInfo
	TimeOut  int // 上传大文件时记得手动拉长超时
}

func debugOutput(msg string) {
	if GlobalDebug {
		slog.Debug(msg)
	}
}

// Ping 📡 微信与服务的健康脉动，轻触即刻，安心无边
// 骑上代码的独角兽，驰骋在微信与服务的和谐旋律中；
// 若路遇荆棘（错误翩翩），WxError的信使将携谜团(-1)翩然而至。
func (*WxApi) Ping() error {
	// 抛出魔法飞毯，直抵全球通讯站(GlobalCallUrl)/ping
	resp, err := http.Get(GlobalCallUrl + "/ping")
	if err != nil {
		// 魔法失效，WxError的封印(-1)悄然降临，记录下不解之谜
		return WxError{-1, err.Error()}
	}
	defer resp.Body.Close() // 隐身术，抹去所有痕迹，不留下一丝涟漪

	// 倾听回响，秘密文字在耳边低语
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		// 文字破碎，WxError的警告(-2)再次响起
		return WxError{-2, err.Error()}
	}

	// 古卷解读，将回响化为RespJson的智慧之光
	rjson := RespJson{}
	json.Unmarshal(data, &rjson)

	// 密文比对，10000是神秘的共鸣密码
	if rjson.Error != 10000 {
		// 密码失真，WxError的困惑(-rjson.Error)引领着归途
		return WxError{rjson.Error, rjson.Msg}
	}

	// 脉动稳健，旅程圆满，一切安好
	return nil
}

// GetUserWeChatVersion 探索微信的奥秘维度
// 跨越星辰大海，追寻新版图的圣杯传说；
// 若遭逢风暴，空荡的圣杯将裹挟WxError的失落归来。
func (*WxApi) GetUserWeChatVersion() (string, error) {
	// 出发，以光年速度驶向微信版本的时空节点
	resp, err := http.Get(GlobalCallUrl + "/GetUserWeChatVersion")
	if err != nil {
		// 时空乱流，WxError的幻影(-1)携破碎梦想现身
		return "", WxError{-1, err.Error()}
	}
	defer resp.Body.Close() // 关闭时空裂隙，以防异界侵袭

	// 接纳圣杯的微光，倾听宇宙的低语
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		// 信息迷失，WxError(-2)的哀歌在虚空中回荡
		return "", WxError{-2, err.Error()}
	}

	// 古老符文解析，揭示RespJson的宇宙密语
	rjson := RespJson{}
	_ = json.Unmarshal(data, &rjson)

	// 密令确认，10000是真理的指引
	if rjson.Error != 10000 {
		// 光芒黯淡，WxError(-rjson.Error)载着谜团回归
		return "", WxError{rjson.Error, rjson.Msg}
	}

	// 圣杯显现，微信版图的最新座标(version)闪耀而出
	return rjson.Data.(map[string]any)["version"].(string), nil
}

// InjectWeChat 微信灵魂注入术，让微信与服务融为一体
// 邀请全球通讯站，完成神秘仪式；
// 若召唤失败，WxError的诅咒将随之降临。
func (w *WxApi) InjectWeChat() (u *UserClientInfo, r error) {
	sl := make(chan int)
	wait := wxInitiativeCallQueue.GetWithSetDefault(loginSuccessMsg, &wxCallQueue{
		Send: make(chan string),
		Resp: make(chan string),
	})
	go func() {
		go func() {
			wait.Send <- "1"
		}()

		const timeout = 99999

		// 等待密信，或迎接时间的审判
		select {
		case message := <-wait.Resp:
			sr := WxLoginInfoResp{}
			err := json.Unmarshal([]byte(message), &sr)
			if err != nil {
				r = WxError{-3, "login timeout"}
				sl <- 0
				break
			}
			w.UserInfo = sr.Data
			registerPid[sr.Data.Pid] = true
			sl <- 1
			// return &w.UserInfo, nil
			break
		case <-time.After(time.Duration(timeout) * time.Second):
			r = WxError{-3, "login timeout"}
			sl <- 0
			break
		}
		//if w.UserInfo.Wxid != "" || r != nil {
		//	break
		//}
	}()
	// 释放灵能，向宇宙宣告召唤
	resp, err := http.Get(GlobalCallUrl + "/InjectWeChat")
	if err != nil {
		// 灵能消散，WxError的阴霾笼罩(-1)
		return nil, WxError{-1, err.Error()}
	}
	defer resp.Body.Close() // 收敛气息，防止泄露

	// 汇聚反馈，领悟回应的奥秘
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		close(wait.Send)
		close(wait.Resp)
		wxInitiativeCallQueue.Delete(loginSuccessMsg)
		// 奥秘难解，WxError的迷雾笼罩(-2)
		return nil, WxError{-2, err.Error()}
	}
	<-sl
	if r != nil {
		return nil, r
	}

	// 解析神秘符号，揭示RespJson的真谛
	var rjson RespJson
	_ = json.Unmarshal(data, &rjson)

	// 检验仪式成功，10000为灵能共鸣的证明
	if rjson.Error != 10000 {
		// 引力失衡，WxError的警告回荡
		return nil, WxError{rjson.Error, rjson.Msg}
	}

	// 仪式圆满，灵能注入，无误返回
	return &w.UserInfo, nil
}

// sendWeChatData 📨 内部秘法，向微信投递加密情报
// 注册ID、客户端ID、JSON数据及超时时限，编织跨越次元的信使；
// 若信使迷失，WxError的幽灵将悄然而至，揭示暗影的谜团。
func (*WxApi) sendWeChatData(registerID, ClientID int, JsonData string, timeout int) (rstr string, rerr error) {
	// 符文编织，信使的护甲，信息封存
	jsonBytes, _ := json.Marshal(map[string]interface{}{
		"ClientId": ClientID,
		"JsonData": JsonData,
	})
	var wait *wxCallQueue
	if registerID != 0 {
		wait = wxInitiativeCallQueue.GetWithSetDefault(registerID, &wxCallQueue{
			Send: make(chan string),
			Resp: make(chan string),
		})
	}

	go func() {
		go func() {
			if registerID != 0 {
				wait.Send <- "1"
			}
		}()
		// 飞翔吧，信使！目标：全球通讯站/SendWeChatData
		url := GlobalCallUrl + "/SendWeChatData"
		req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
		if err != nil {
			rerr = WxError{
				ErrorCode: -1,
				Message:   fmt.Sprintf("Error crafting message: %v", err),
			}
			return
		}
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			rerr = WxError{
				ErrorCode: -2,
				Message:   fmt.Sprintf("Error delivering message: %v", err),
			}
			return
		}
		defer resp.Body.Close()

	}()
	if registerID != 0 {
		if timeout == 0 {
			timeout = 999999
		}
		if timeout > 0 {
			select {
			case message := <-wait.Resp:
				return message, nil
			case <-time.After(time.Duration(timeout) * time.Second):
				return "", WxError{-3, "request timeout"}
			}
		}
	}

	return
}

// internalCall
func (w *WxApi) internalCall(registerID, timeout, Type int, JsonData any, trace any) (string, error) {
	send := map[string]interface{}{
		"type": Type,
	}
	if JsonData != nil {
		send["data"] = JsonData
	}
	if trace != nil {
		send["trace"] = trace
	}

	jsonBytes, _ := json.Marshal(send)

	return w.sendWeChatData(registerID, 1, string(jsonBytes), timeout)
}
