package draft

import (
	"fmt"

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

const (
	addURL      = "https://api.weixin.qq.com/cgi-bin/draft/add"      // 新建草稿
	getURL      = "https://api.weixin.qq.com/cgi-bin/draft/get"      // 获取草稿
	deleteURL   = "https://api.weixin.qq.com/cgi-bin/draft/delete"   // 删除草稿
	updateURL   = "https://api.weixin.qq.com/cgi-bin/draft/update"   // 修改草稿
	countURL    = "https://api.weixin.qq.com/cgi-bin/draft/count"    // 获取草稿总数
	paginateURL = "https://api.weixin.qq.com/cgi-bin/draft/batchget" // 获取草稿列表
)

// Draft 草稿箱
type Draft struct {
	*context.Context
}

// NewDraft init
func NewDraft(ctx *context.Context) *Draft {
	return &Draft{
		Context: ctx,
	}
}

// Article 草稿
type Article struct {
	Title              string `json:"title"`                 // 标题
	Author             string `json:"author"`                // 作者
	Digest             string `json:"digest"`                // 图文消息的摘要，仅有单图文消息才有摘要，多图文此处为空。
	Content            string `json:"content"`               // 图文消息的具体内容，支持HTML标签，必须少于2万字符，小于1M，且去除JS
	ContentSourceURL   string `json:"content_source_url"`    // 图文消息的原文地址，即点击“阅读原文”后的URL
	ThumbMediaID       string `json:"thumb_media_id"`        // 图文消息的封面图片素材id（必须是永久MediaID）
	ShowCoverPic       uint   `json:"show_cover_pic"`        // 是否显示封面，0为false，即不显示，1为true，即显示(默认)
	NeedOpenComment    uint   `json:"need_open_comment"`     // 是否打开评论，0不打开(默认)，1打开
	OnlyFansCanComment uint   `json:"only_fans_can_comment"` // 是否粉丝才可评论，0所有人可评论(默认)，1粉丝才可评论
}

// AddDraft 新建草稿
func (draft *Draft) AddDraft(articles []*Article) (mediaID string, err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var req struct {
		Articles []*Article `json:"articles"`
	}
	req.Articles = articles

	uri := fmt.Sprintf("%s?access_token=%s", addURL, accessToken)
	response, err := util.PostJSON(uri, req)
	if err != nil {
		return
	}

	var res struct {
		util.CommonError
		MediaID string `json:"media_id"`
	}
	err = util.DecodeWithError(response, &res, "AddDraft")
	if err != nil {
		return
	}
	mediaID = res.MediaID
	return
}

// GetDraft 获取草稿
func (draft *Draft) GetDraft(mediaID string) (articles []*Article, err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var req struct {
		MediaID string `json:"media_id"`
	}
	req.MediaID = mediaID

	uri := fmt.Sprintf("%s?access_token=%s", getURL, accessToken)
	response, err := util.PostJSON(uri, req)
	if err != nil {
		return
	}

	var res struct {
		util.CommonError
		NewsItem []*Article `json:"news_item"`
	}
	err = util.DecodeWithError(response, &res, "GetDraft")
	if err != nil {
		return
	}

	articles = res.NewsItem
	return
}

// DeleteDraft 删除草稿
func (draft *Draft) DeleteDraft(mediaID string) (err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var req struct {
		MediaID string `json:"media_id"`
	}
	req.MediaID = mediaID

	var response []byte
	uri := fmt.Sprintf("%s?access_token=%s", deleteURL, accessToken)
	response, err = util.PostJSON(uri, req)
	if err != nil {
		return
	}

	err = util.DecodeWithCommonError(response, "DeleteDraft")
	return
}

// UpdateDraft 修改草稿
// index 要更新的文章在图文消息中的位置（多图文消息时，此字段才有意义），第一篇为0
func (draft *Draft) UpdateDraft(article *Article, mediaID string, index uint) (err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var req struct {
		MediaID string   `json:"media_id"`
		Index   uint     `json:"index"`
		Article *Article `json:"articles"`
	}
	req.MediaID = mediaID
	req.Index = index
	req.Article = article

	uri := fmt.Sprintf("%s?access_token=%s", updateURL, accessToken)
	var response []byte
	response, err = util.PostJSON(uri, req)
	if err != nil {
		return
	}

	err = util.DecodeWithCommonError(response, "UpdateDraft")
	return
}

// CountDraft 获取草稿总数
func (draft *Draft) CountDraft() (total uint, err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var response []byte
	uri := fmt.Sprintf("%s?access_token=%s", countURL, accessToken)
	response, err = util.HTTPGet(uri)
	if err != nil {
		return
	}

	var res struct {
		util.CommonError
		Total uint `json:"total_count"`
	}
	err = util.DecodeWithError(response, &res, "CountDraft")
	if nil != err {
		return
	}

	total = res.Total
	return
}

// ArticleList 草稿列表
type ArticleList struct {
	util.CommonError
	TotalCount int64             `json:"total_count"` // 草稿素材的总数
	ItemCount  int64             `json:"item_count"`  // 本次调用获取的素材的数量
	Item       []ArticleListItem `json:"item"`
}

// ArticleListItem 用于 ArticleList 的 item 节点
type ArticleListItem struct {
	MediaID    string             `json:"media_id"`    // 图文消息的id
	Content    ArticleListContent `json:"content"`     // 内容
	UpdateTime int64              `json:"update_time"` // 这篇图文消息素材的最后更新时间
}

// ArticleListContent 用于 ArticleListItem 的 content 节点
type ArticleListContent struct {
	NewsItem []Article `json:"news_item"` // 这篇图文消息素材的内容
}

// PaginateDraft 获取草稿列表
func (draft *Draft) PaginateDraft(offset, count int64, noReturnContent bool) (list ArticleList, err error) {
	accessToken, err := draft.GetAccessToken()
	if err != nil {
		return
	}

	var req struct {
		Count           int64 `json:"count"`
		Offset          int64 `json:"offset"`
		NoReturnContent bool  `json:"no_content"`
	}
	req.Count = count
	req.Offset = offset
	req.NoReturnContent = noReturnContent

	var response []byte
	uri := fmt.Sprintf("%s?access_token=%s", paginateURL, accessToken)
	response, err = util.PostJSON(uri, req)
	if err != nil {
		return
	}

	err = util.DecodeWithError(response, &list, "PaginateDraft")
	return
}
