package wechat

import (
	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/auth/wechat"
	"code.gitea.io/gitea/modules/notification"
	"code.gitea.io/gitea/modules/redis/redis_client"
	"code.gitea.io/gitea/modules/redis/redis_key"
	"encoding/json"
	"encoding/xml"
	"strings"
	"time"
)

//<xml>
//  <ToUserName><![CDATA[toUser]]></ToUserName>
//  <FromUserName><![CDATA[FromUser]]></FromUserName>
//  <CreateTime>123456789</CreateTime>
//  <MsgType><![CDATA[event]]></MsgType>
//  <Event><![CDATA[SCAN]]></Event>
//  <EventKey><![CDATA[SCENE_VALUE]]></EventKey>
//  <Ticket><![CDATA[TICKET]]></Ticket>
//</xml>
type WechatMsg struct {
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Event        string
	EventKey     string
	Ticket       string
	Content      string
	MsgId        string
	MsgDataId    string
	Idx          string
}

type MsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Content      string
}

type TextMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Content      string
}
type ImageMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Image        ImageContent
}
type VoiceMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Voice        VoiceContent
}
type VideoMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Video        VideoContent
}
type MusicMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	Music        MusicContent
}
type NewsMsgReply struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string
	FromUserName string
	CreateTime   int64
	MsgType      string
	ArticleCount int
	Articles     ArticleItem
}

type ArticleItem struct {
	Item []ArticlesContent
}

type ImageContent struct {
	MediaId string
}
type VoiceContent struct {
	MediaId string
}
type VideoContent struct {
	MediaId     string
	Title       string
	Description string
}
type MusicContent struct {
	Title        string
	Description  string
	MusicUrl     string
	HQMusicUrl   string
	ThumbMediaId string
}
type ArticlesContent struct {
	XMLName     xml.Name `xml:"item"`
	Title       string
	Description string
	PicUrl      string
	Url         string
}

const (
	WECHAT_EVENT_SUBSCRIBE = "subscribe"
	WECHAT_EVENT_SCAN      = "SCAN"
)

const (
	WECHAT_MSG_TYPE_TEXT  = "text"
	WECHAT_MSG_TYPE_EVENT = "event"
)

func HandleScanEvent(we WechatMsg) string {
	eventKey := we.EventKey
	if eventKey == "" {
		return ""
	}
	sceneStr := strings.TrimPrefix(eventKey, "qrscene_")
	key := redis_key.WechatBindingUserIdKey(sceneStr)
	val, _ := redis_client.Get(key)
	if val == "" {
		return ""
	}
	qrCache := new(wechat.QRCode4BindCache)
	json.Unmarshal([]byte(val), qrCache)
	if qrCache.Status == wechat.BIND_STATUS_UNBIND {
		err := wechat.BindWechat(qrCache.UserId, we.FromUserName)
		if err != nil {
			if err, ok := err.(wechat.WechatBindError); ok {
				return err.Reply
			}
			return wechat.BIND_REPLY_FAILED_DEFAULT
		}
		qrCache.Status = wechat.BIND_STATUS_BOUND
		jsonStr, _ := json.Marshal(qrCache)
		redis_client.Setex(redis_key.WechatBindingUserIdKey(sceneStr), string(jsonStr), 60*time.Second)
	}
	u, err := models.GetUserByID(qrCache.UserId)
	if err == nil {
		notification.NotifyWechatBind(u, we.FromUserName)
	}

	return wechat.BIND_REPLY_SUCCESS
}

func HandleSubscribeEvent(we WechatMsg) *WechatReplyContent {
	r, err := LoadReplyFromCacheAndDisk(SubscribeReply)
	if err != nil || len(r) == 0 {
		return nil
	}
	return r[0]
}
