package dingtalk

// 旧版sdk客户端 - 在用，勿删！

import (
	"ai_scheduler/internal/config"
	"ai_scheduler/internal/pkg/l_request"
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/faabiosr/cachego/file"
	"github.com/fastwego/dingding"
)

type OldClient struct {
	config *config.Config
	cli    *dingding.Client
	atm    *dingding.DefaultAccessTokenManager
}

func NewOldClient(config *config.Config) *OldClient {
	atm := &dingding.DefaultAccessTokenManager{
		Id:   config.Tools.DingTalkBot.APIKey,
		Name: "access_token",
		GetRefreshRequestFunc: func() *http.Request {
			params := url.Values{}
			params.Add("appkey", config.Tools.DingTalkBot.APIKey)
			params.Add("appsecret", config.Tools.DingTalkBot.APISecret)
			req, _ := http.NewRequest(http.MethodGet, dingding.ServerUrl+"/gettoken?"+params.Encode(), nil)
			return req
		},
		Cache: file.New(os.TempDir()),
	}
	return &OldClient{config: config, cli: dingding.NewClient(atm), atm: atm}
}

type UserDetail struct {
	UserID  string `json:"userid"`
	Name    string `json:"name"`
	UnionID string `json:"unionid"`
}

func (c *OldClient) do(ctx context.Context, method, path string, body []byte) ([]byte, error) {
	var r io.Reader
	if body != nil {
		r = bytes.NewReader(body)
	}
	req, err := http.NewRequestWithContext(ctx, method, path, r)
	if err != nil {
		return nil, err
	}
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	return c.cli.Do(req)
}

func (c *OldClient) QueryUserDetails(ctx context.Context, userId string) (*UserDetail, error) {
	body := struct {
		UserId   string `json:"userid"`
		Language string `json:"language,omitempty"`
	}{UserId: userId, Language: "zh_CN"}
	b, _ := json.Marshal(body)
	res, err := c.do(ctx, http.MethodPost, "/topapi/v2/user/get", b)
	if err != nil {
		return nil, err
	}
	var resp struct {
		Code   int        `json:"errcode"`
		Msg    string     `json:"errmsg"`
		Result UserDetail `json:"result"`
	}
	if err := json.Unmarshal(res, &resp); err != nil {
		return nil, err
	}
	if resp.Code != 0 {
		return nil, errors.New(resp.Msg)
	}
	return &resp.Result, nil
}

func (c *OldClient) QueryUserDetailsByMobile(ctx context.Context, mobile string) (*UserDetail, error) {
	body := struct {
		Mobile string `json:"mobile"`
	}{Mobile: mobile}
	b, _ := json.Marshal(body)
	res, err := c.do(ctx, http.MethodPost, "/topapi/v2/user/getbymobile", b)
	if err != nil {
		return nil, err
	}
	var resp struct {
		Code   int        `json:"errcode"`
		Msg    string     `json:"errmsg"`
		Result UserDetail `json:"result"`
	}
	if err := json.Unmarshal(res, &resp); err != nil {
		return nil, err
	}
	if resp.Code != 0 {
		return nil, errors.New(resp.Msg)
	}
	return &resp.Result, nil
}

// GetAccessToken 通过 fastwego 的 AccessTokenManager 获取当前可用 access_token
func (c *OldClient) GetAccessToken() (string, error) {
	return c.atm.GetAccessToken()
}

// CreateInternalGroupConversation 创建企业内部群聊
func (c *OldClient) CreateInternalGroupConversation(ctx context.Context, accessToken, groupName string, userIds []string) (chatId, openConversationId string, err error) {
	body := struct {
		Name                string   `json:"name"`
		Owner               string   `json:"owner"`
		UserIds             []string `json:"useridlist"`
		ShowHistoryType     int      `json:"showHistoryType"`
		Searchable          int      `json:"searchable"`
		ValidationType      int      `json:"validationType"`
		MentionAllAuthority int      `json:"mentionAllAuthority"`
		ManagementType      int      `json:"managementType"`
		ChatBannedType      int      `json:"chatBannedType"`
	}{
		Name:    groupName,
		Owner:   userIds[0],
		UserIds: userIds,
	}
	b, _ := json.Marshal(body)

	req := l_request.Request{
		Method:   "POST",
		JsonByte: b,
		Url:      "https://oapi.dingtalk.com/chat/create?access_token=" + accessToken,
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	}
	res, err := req.Send()
	if err != nil {
		return
	}

	var resp struct {
		Code               int    `json:"errcode"`
		Msg                string `json:"errmsg"`
		ChatId             string `json:"chatid"`
		OpenConversationId string `json:"openConversationId"`
		ConversationTag    int    `json:"conversationTag"`
	}
	if err = json.Unmarshal(res.Content, &resp); err != nil {
		return
	}
	if resp.Code != 0 {
		return "", "", errors.New(resp.Msg)
	}

	return resp.ChatId, resp.OpenConversationId, nil
}

// CreateSceneGroupConversation 创建场景群-基于群模板
func (c *OldClient) CreateSceneGroupConversation(ctx context.Context, accessToken, groupName string, userIds []string, templateId string) (chatId, openConversationId string, err error) {
	body := struct {
		Title                       string `json:"title"`                           // 群名称
		TemplateId                  string `json:"template_id"`                     // 群模板ID
		OwnerUserID                 string `json:"owner_user_id"`                   // 群主的userid。
		UserIds                     string `json:"user_ids"`                        // 群成员userid列表。
		SubAdminIds                 string `json:"subadmin_ids"`                    // 群管理员userid列表。
		UUID                        string `json:"uuid"`                            // 建群去重的业务ID，由接口调用方指定。
		Icon                        string `json:"icon"`                            // 群头像，格式为mediaId。需要调用上传媒体文件接口上传群头像，获取mediaId。
		MentionAllAuthority         int    `json:"mention_all_authority"`           // @all 权限：0（默认）：所有人都可以@all 1：仅群主可@all
		ShowHistoryType             int    `json:"show_history_type"`               // 新成员是否可查看聊天历史消息：0（默认）：不可以查看历史记录 1：可以查看历史记录
		ValidationType              int    `json:"validation_type"`                 // 入群是否需要验证：0（默认）：不验证入群 1：入群验证
		Searchable                  int    `json:"searchable"`                      // 群是否可搜索：0（默认）：不可搜索 1：可搜索
		ChatBannedType              int    `json:"chat_banned_type"`                // 是否开启群禁言：0（默认）：不禁言 1：全员禁言
		ManagementType              int    `json:"management_type"`                 // 管理类型：0（默认）：所有人可管理 1：仅群主可管理
		OnlyAdminCanDing            int    `json:"only_admin_can_ding"`             // 群内发DING权限：0（默认）：所有人可发DING 1：仅群主和管理员可发DING
		AllMembersCanCreateMcsConf  int    `json:"all_members_can_create_mcs_conf"` // 群会议权限：0：仅群主和管理员可发起视频和语音会议 1（默认）：所有人可发起视频和语音会议
		AllMembersCanCreateCalendar int    `json:"all_members_can_create_calendar"` // 群日历权限：0：仅群主和管理员可创建群日历 1（默认）：所有人可创建群日历
		GroupEmailDisabled          int    `json:"group_email_disabled"`            // 群邮件权限：0（默认）：群内成员可以对本群发送群邮件 1：群内成员不可对本群发送群邮件
		OnlyAdminCanSetMsgTop       int    `json:"only_admin_can_set_msg_top"`      // 置顶群消息权限：0（默认）：所有人可置顶群消息 1：仅群主和管理员可置顶群消息
		AddFriendForbidden          int    `json:"add_friend_forbidden"`            // 群成员私聊权限：0（默认）：所有人可私聊 1：普通群成员之间不能够加好友、单聊，且部分功能使用受限（管理员与非管理员之间不受影响）
		GroupLiveSwitch             int    `json:"group_live_switch"`               // 群直播权限：0：仅群主与管理员可发起直播 1（默认）：群内任意成员可发起群直播
		MembersToAdminChat          int    `json:"members_to_admin_chat"`           // 是否禁止非管理员向管理员发起单聊：0（默认）：非管理员可以向管理员发起单聊 1：禁止非管理员向管理员发起单聊
	}{
		Title:       groupName,
		TemplateId:  templateId,
		OwnerUserID: userIds[0],
		UserIds:     strings.Join(userIds, ","),
		SubAdminIds: strings.Join(userIds, ","),
	}

	b, _ := json.Marshal(body)

	req := l_request.Request{
		Method:   "POST",
		JsonByte: b,
		Url:      "https://oapi.dingtalk.com/topapi/im/chat/scenegroup/create?access_token=" + accessToken,
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	}
	res, err := req.Send()
	if err != nil {
		return
	}

	var resp struct {
		Code   int    `json:"errcode"`
		Msg    string `json:"errmsg"`
		Result struct {
			ChatId             string `json:"chat_id"`
			OpenConversationId string `json:"open_conversation_id"`
		} `json:"result"`
	}
	if err = json.Unmarshal(res.Content, &resp); err != nil {
		return
	}
	if resp.Code != 0 {
		return "", "", errors.New(resp.Msg)
	}
	return resp.Result.ChatId, resp.Result.OpenConversationId, nil
}

// 获取入群二维码链接
func (c *OldClient) GetJoinGroupQrcode(ctx context.Context, chatId, userId string) (string, error) {
	body := struct {
		ChatId string `json:"chatid"`
		UserId string `json:"userid"`
	}{ChatId: chatId, UserId: userId}
	b, _ := json.Marshal(body)
	res, err := c.do(ctx, http.MethodPost, "/topapi/chat/qrcode/get", b)
	if err != nil {
		return "", err
	}
	var resp struct {
		Code   int    `json:"errcode"`
		Msg    string `json:"errmsg"`
		Result string `json:"result"`
	}
	if err := json.Unmarshal(res, &resp); err != nil {
		return "", err
	}
	if resp.Code != 0 {
		return "", errors.New(resp.Msg)
	}
	return resp.Result, nil
}
