package externalcontact

import (
	"encoding/json"
	"fmt"

	"github.com/silenceper/wechat/v2/util"
)

const (
	// fetchExternalContactUserListURL 获取客户列表
	fetchExternalContactUserListURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list"
	// fetchExternalContactUserDetailURL 获取客户详情
	fetchExternalContactUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get"
	// fetchBatchExternalContactUserDetailURL 批量获取客户详情
	fetchBatchExternalContactUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user"
	// updateUserRemarkURL 更新客户备注信息
	updateUserRemarkURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark"
	// listCustomerStrategyURL 获取规则组列表
	listCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/list?access_token=%s"
	// getCustomerStrategyURL 获取规则组详情
	getCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/get?access_token=%s"
	// getRangeCustomerStrategyURL 获取规则组管理范围
	getRangeCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/get_range?access_token=%s"
	// createCustomerStrategyURL 创建新的规则组
	createCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/create?access_token=%s"
	// editCustomerStrategyURL 编辑规则组及其管理范围
	editCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/edit?access_token=%s"
	// delCustomerStrategyURL 删除规则组
	delCustomerStrategyURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_strategy/del?access_token=%s"
)

// ExternalUserListResponse 外部联系人列表响应
type ExternalUserListResponse struct {
	util.CommonError
	ExternalUserID []string `json:"external_userid"`
}

// GetExternalUserList 获取客户列表
// @see https://developer.work.weixin.qq.com/document/path/92113
func (r *Client) GetExternalUserList(userID string) ([]string, error) {
	accessToken, err := r.GetAccessToken()
	if err != nil {
		return nil, err
	}
	var response []byte
	response, err = util.HTTPGet(fmt.Sprintf("%s?access_token=%v&userid=%v", fetchExternalContactUserListURL, accessToken, userID))
	if err != nil {
		return nil, err
	}
	var result ExternalUserListResponse
	err = util.DecodeWithError(response, &result, "GetExternalUserList")
	return result.ExternalUserID, err
}

// ExternalUserDetailResponse 外部联系人详情响应
type ExternalUserDetailResponse struct {
	util.CommonError
	ExternalContact ExternalUser `json:"external_contact"`
	FollowUser      []FollowUser `json:"follow_user"`
	NextCursor      string       `json:"next_cursor"`
}

// ExternalUser 外部联系人
type ExternalUser struct {
	ExternalUserID  string           `json:"external_userid"`
	Name            string           `json:"name"`
	Avatar          string           `json:"avatar"`
	Type            int64            `json:"type"`
	Gender          int64            `json:"gender"`
	UnionID         string           `json:"unionid"`
	Position        string           `json:"position"`
	CorpName        string           `json:"corp_name"`
	CorpFullName    string           `json:"corp_full_name"`
	ExternalProfile *ExternalProfile `json:"external_profile,omitempty"`
}

// FollowUser 跟进用户（指企业内部用户）
type FollowUser struct {
	UserID         string        `json:"userid"`
	Remark         string        `json:"remark"`
	Description    string        `json:"description"`
	CreateTime     int64         `json:"createtime"`
	Tags           []Tag         `json:"tags"`
	RemarkCorpName string        `json:"remark_corp_name"`
	RemarkMobiles  []string      `json:"remark_mobiles"`
	OperUserID     string        `json:"oper_userid"`
	AddWay         int64         `json:"add_way"`
	WeChatChannels WechatChannel `json:"wechat_channels"`
	State          string        `json:"state"`
}

// Tag 已绑定在外部联系人的标签
type Tag struct {
	GroupName string `json:"group_name"`
	TagName   string `json:"tag_name"`
	Type      int64  `json:"type"`
	TagID     string `json:"tag_id"`
}

// WechatChannel 视频号添加的场景
type WechatChannel struct {
	NickName string `json:"nickname"`
	Source   int    `json:"source"`
}

// ExternalProfile 外部联系人的自定义展示信息,可以有多个字段和多种类型，包括文本，网页和小程序
type ExternalProfile struct {
	ExternalCorpName string         `json:"external_corp_name"`
	WechatChannels   WechatChannels `json:"wechat_channels"`
	ExternalAttr     []ExternalAttr `json:"external_attr"`
}

// WechatChannels 视频号属性。须从企业绑定到企业微信的视频号中选择，可在“我的企业”页中查看绑定的视频号
type WechatChannels struct {
	Nickname string `json:"nickname"`
	Status   int    `json:"status"`
}

// ExternalAttr 属性列表，目前支持文本、网页、小程序三种类型
type ExternalAttr struct {
	Type        int          `json:"type"`
	Name        string       `json:"name"`
	Text        *Text        `json:"text,omitempty"`
	Web         *Web         `json:"web,omitempty"`
	MiniProgram *MiniProgram `json:"miniprogram,omitempty"`
}

// Text 文本
type Text struct {
	Value string `json:"value"`
}

// Web 网页
type Web struct {
	URL   string `json:"url"`
	Title string `json:"title"`
}

// MiniProgram 小程序
type MiniProgram struct {
	AppID    string `json:"appid"`
	Pagepath string `json:"pagepath"`
	Title    string `json:"title"`
}

// GetExternalUserDetail 获取外部联系人详情
// @see https://developer.work.weixin.qq.com/document/path/92114
func (r *Client) GetExternalUserDetail(externalUserID string, nextCursor ...string) (*ExternalUserDetailResponse, error) {
	accessToken, err := r.GetAccessToken()
	if err != nil {
		return nil, err
	}
	var response []byte
	var cursor string
	if len(nextCursor) > 0 {
		cursor = nextCursor[0]
	}
	response, err = util.HTTPGet(fmt.Sprintf("%s?access_token=%v&external_userid=%v&cursor=%v", fetchExternalContactUserDetailURL, accessToken, externalUserID, cursor))
	if err != nil {
		return nil, err
	}
	result := &ExternalUserDetailResponse{}
	err = util.DecodeWithError(response, result, "get_external_user_detail")
	return result, err
}

// BatchGetExternalUserDetailsRequest 批量获取外部联系人详情请求
type BatchGetExternalUserDetailsRequest struct {
	UserIDList []string `json:"userid_list"`
	Cursor     string   `json:"cursor"`
	Limit      int      `json:"limit,omitempty"`
}

// ExternalUserDetailListResponse 批量获取外部联系人详情响应
type ExternalUserDetailListResponse struct {
	util.CommonError
	ExternalContactList []ExternalUserForBatch `json:"external_contact_list"`
}

// ExternalUserForBatch 批量获取外部联系人客户列表
type ExternalUserForBatch struct {
	ExternalContact ExternalContact `json:"external_contact"`
	FollowInfo      FollowInfo      `json:"follow_info"`
}

// ExternalContact 批量获取外部联系人用户信息
type ExternalContact struct {
	ExternalUserID  string `json:"external_userid"`
	Name            string `json:"name"`
	Position        string `json:"position"`
	Avatar          string `json:"avatar"`
	CorpName        string `json:"corp_name"`
	CorpFullName    string `json:"corp_full_name"`
	Type            int64  `json:"type"`
	Gender          int64  `json:"gender"`
	UnionID         string `json:"unionid"`
	ExternalProfile string `json:"external_profile"`
}

// FollowInfo 批量获取外部联系人跟进人信息
type FollowInfo struct {
	UserID         string        `json:"userid"`
	Remark         string        `json:"remark"`
	Description    string        `json:"description"`
	CreateTime     int64         `json:"createtime"`
	TagID          []string      `json:"tag_id"`
	RemarkCorpName string        `json:"remark_corp_name"`
	RemarkMobiles  []string      `json:"remark_mobiles"`
	OperUserID     string        `json:"oper_userid"`
	AddWay         int64         `json:"add_way"`
	WeChatChannels WechatChannel `json:"wechat_channels"`
}

// BatchGetExternalUserDetails 批量获取外部联系人详情
// @see https://developer.work.weixin.qq.com/document/path/92994
func (r *Client) BatchGetExternalUserDetails(request BatchGetExternalUserDetailsRequest) ([]ExternalUserForBatch, error) {
	accessToken, err := r.GetAccessToken()
	if err != nil {
		return nil, err
	}
	var response []byte
	jsonData, err := json.Marshal(request)
	if err != nil {
		return nil, err
	}
	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", fetchBatchExternalContactUserDetailURL, accessToken), string(jsonData))
	if err != nil {
		return nil, err
	}
	var result ExternalUserDetailListResponse
	err = util.DecodeWithError(response, &result, "BatchGetExternalUserDetails")
	return result.ExternalContactList, err
}

// UpdateUserRemarkRequest 修改客户备注信息请求体
type UpdateUserRemarkRequest struct {
	UserID           string   `json:"userid"`
	ExternalUserID   string   `json:"external_userid"`
	Remark           string   `json:"remark"`
	Description      string   `json:"description"`
	RemarkCompany    string   `json:"remark_company"`
	RemarkMobiles    []string `json:"remark_mobiles"`
	RemarkPicMediaID string   `json:"remark_pic_mediaid"`
}

// UpdateUserRemark 修改客户备注信息
// @see https://developer.work.weixin.qq.com/document/path/92115
func (r *Client) UpdateUserRemark(request UpdateUserRemarkRequest) error {
	accessToken, err := r.GetAccessToken()
	if err != nil {
		return err
	}
	var response []byte
	jsonData, err := json.Marshal(request)
	if err != nil {
		return err
	}
	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", updateUserRemarkURL, accessToken), string(jsonData))
	if err != nil {
		return err
	}
	return util.DecodeWithCommonError(response, "UpdateUserRemark")
}

// ListCustomerStrategyRequest 获取规则组列表请求
type ListCustomerStrategyRequest struct {
	Cursor string `json:"cursor"`
	Limit  int    `json:"limit"`
}

// ListCustomerStrategyResponse 获取规则组列表响应
type ListCustomerStrategyResponse struct {
	util.CommonError
	Strategy   []StrategyID `json:"strategy"`
	NextCursor string       `json:"next_cursor"`
}

// StrategyID 规则组ID
type StrategyID struct {
	StrategyID int `json:"strategy_id"`
}

// ListCustomerStrategy 获取规则组列表
// @see https://developer.work.weixin.qq.com/document/path/94883#%E8%8E%B7%E5%8F%96%E8%A7%84%E5%88%99%E7%BB%84%E5%88%97%E8%A1%A8
func (r *Client) ListCustomerStrategy(req *ListCustomerStrategyRequest) (*ListCustomerStrategyResponse, error) {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return nil, err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(listCustomerStrategyURL, accessToken), req); err != nil {
		return nil, err
	}
	result := &ListCustomerStrategyResponse{}
	err = util.DecodeWithError(response, result, "ListCustomerStrategy")
	return result, err
}

// GetCustomerStrategyRequest 获取规则组详情请求
type GetCustomerStrategyRequest struct {
	StrategyID int `json:"strategy_id"`
}

// GetCustomerStrategyResponse 获取规则组详情响应
type GetCustomerStrategyResponse struct {
	util.CommonError
	Strategy Strategy `json:"strategy"`
}

// Strategy 规则组
type Strategy struct {
	StrategyID   int       `json:"strategy_id"`
	ParentID     int       `json:"parent_id"`
	StrategyName string    `json:"strategy_name"`
	CreateTime   int64     `json:"create_time"`
	AdminList    []string  `json:"admin_list"`
	Privilege    Privilege `json:"privilege"`
}

// Privilege 权限
type Privilege struct {
	ViewCustomerList        bool `json:"view_customer_list"`
	ViewCustomerData        bool `json:"view_customer_data"`
	ViewRoomList            bool `json:"view_room_list"`
	ContactMe               bool `json:"contact_me"`
	JoinRoom                bool `json:"join_room"`
	ShareCustomer           bool `json:"share_customer"`
	OperResignCustomer      bool `json:"oper_resign_customer"`
	OperResignGroup         bool `json:"oper_resign_group"`
	SendCustomerMsg         bool `json:"send_customer_msg"`
	EditWelcomeMsg          bool `json:"edit_welcome_msg"`
	ViewBehaviorData        bool `json:"view_behavior_data"`
	ViewRoomData            bool `json:"view_room_data"`
	SendGroupMsg            bool `json:"send_group_msg"`
	RoomDeduplication       bool `json:"room_deduplication"`
	RapidReply              bool `json:"rapid_reply"`
	OnjobCustomerTransfer   bool `json:"onjob_customer_transfer"`
	EditAntiSpamRule        bool `json:"edit_anti_spam_rule"`
	ExportCustomerList      bool `json:"export_customer_list"`
	ExportCustomerData      bool `json:"export_customer_data"`
	ExportCustomerGroupList bool `json:"export_customer_group_list"`
	ManageCustomerTag       bool `json:"manage_customer_tag"`
}

// GetCustomerStrategy 获取规则组详情
// @see https://developer.work.weixin.qq.com/document/path/94883#%E8%8E%B7%E5%8F%96%E8%A7%84%E5%88%99%E7%BB%84%E8%AF%A6%E6%83%85
func (r *Client) GetCustomerStrategy(req *GetCustomerStrategyRequest) (*GetCustomerStrategyResponse, error) {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return nil, err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(getCustomerStrategyURL, accessToken), req); err != nil {
		return nil, err
	}
	result := &GetCustomerStrategyResponse{}
	err = util.DecodeWithError(response, result, "GetCustomerStrategy")
	return result, err
}

// GetRangeCustomerStrategyRequest 获取规则组管理范围请求
type GetRangeCustomerStrategyRequest struct {
	StrategyID int    `json:"strategy_id"`
	Cursor     string `json:"cursor"`
	Limit      int    `json:"limit"`
}

// GetRangeCustomerStrategyResponse 获取规则组管理范围响应
type GetRangeCustomerStrategyResponse struct {
	util.CommonError
	Range      []Range `json:"range"`
	NextCursor string  `json:"next_cursor"`
}

// Range 管理范围节点
type Range struct {
	Type    int    `json:"type"`
	UserID  string `json:"userid,omitempty"`
	PartyID int    `json:"partyid,omitempty"`
}

// GetRangeCustomerStrategy 获取规则组管理范围
// @see https://developer.work.weixin.qq.com/document/path/94883#%E8%8E%B7%E5%8F%96%E8%A7%84%E5%88%99%E7%BB%84%E7%AE%A1%E7%90%86%E8%8C%83%E5%9B%B4
func (r *Client) GetRangeCustomerStrategy(req *GetRangeCustomerStrategyRequest) (*GetRangeCustomerStrategyResponse, error) {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return nil, err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(getRangeCustomerStrategyURL, accessToken), req); err != nil {
		return nil, err
	}
	result := &GetRangeCustomerStrategyResponse{}
	err = util.DecodeWithError(response, result, "GetRangeCustomerStrategy")
	return result, err
}

// CreateCustomerStrategyRequest 创建新的规则组请求
type CreateCustomerStrategyRequest struct {
	ParentID     int       `json:"parent_id"`
	StrategyName string    `json:"strategy_name"`
	AdminList    []string  `json:"admin_list"`
	Privilege    Privilege `json:"privilege"`
	Range        []Range   `json:"range"`
}

// CreateCustomerStrategyResponse 创建新的规则组响应
type CreateCustomerStrategyResponse struct {
	util.CommonError
	StrategyID int `json:"strategy_id"`
}

// CreateCustomerStrategy 创建新的规则组
// @see https://developer.work.weixin.qq.com/document/path/94883#%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84%E8%A7%84%E5%88%99%E7%BB%84
func (r *Client) CreateCustomerStrategy(req *CreateCustomerStrategyRequest) (*CreateCustomerStrategyResponse, error) {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return nil, err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(createCustomerStrategyURL, accessToken), req); err != nil {
		return nil, err
	}
	result := &CreateCustomerStrategyResponse{}
	err = util.DecodeWithError(response, result, "CreateCustomerStrategy")
	return result, err
}

// EditCustomerStrategyRequest 编辑规则组及其管理范围请求
type EditCustomerStrategyRequest struct {
	StrategyID   int       `json:"strategy_id"`
	StrategyName string    `json:"strategy_name"`
	AdminList    []string  `json:"admin_list"`
	Privilege    Privilege `json:"privilege"`
	RangeAdd     []Range   `json:"range_add"`
	RangeDel     []Range   `json:"range_del"`
}

// EditCustomerStrategy 编辑规则组及其管理范围
// see https://developer.work.weixin.qq.com/document/path/94883#%E7%BC%96%E8%BE%91%E8%A7%84%E5%88%99%E7%BB%84%E5%8F%8A%E5%85%B6%E7%AE%A1%E7%90%86%E8%8C%83%E5%9B%B4
func (r *Client) EditCustomerStrategy(req *EditCustomerStrategyRequest) error {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(editCustomerStrategyURL, accessToken), req); err != nil {
		return err
	}
	return util.DecodeWithCommonError(response, "EditCustomerStrategy")
}

// DelCustomerStrategyRequest 删除规则组请求
type DelCustomerStrategyRequest struct {
	StrategyID int `json:"strategy_id"`
}

// DelCustomerStrategy 删除规则组
// see https://developer.work.weixin.qq.com/document/path/94883#%E5%88%A0%E9%99%A4%E8%A7%84%E5%88%99%E7%BB%84
func (r *Client) DelCustomerStrategy(req *DelCustomerStrategyRequest) error {
	var (
		accessToken string
		err         error
	)
	if accessToken, err = r.GetAccessToken(); err != nil {
		return err
	}
	var response []byte
	if response, err = util.PostJSON(fmt.Sprintf(delCustomerStrategyURL, accessToken), req); err != nil {
		return err
	}
	return util.DecodeWithCommonError(response, "DelCustomerStrategy")
}
