package v1

import (
	"context"
	"encoding/json"

	"github.com/pingcap-inc/pingcat/internal/apiserver/store"
	"github.com/pingcap-inc/pingcat/internal/pkg/code"
	"github.com/pingcap-inc/pingcat/internal/pkg/rstore"

	"github.com/pingcap-inc/pchub/pkg/errors"
	"github.com/pingcap-inc/pchub/pkg/log"
	"github.com/pingcap-inc/pchub/pkg/rstorage"
)

type LarkChatService struct {
	store store.Factory
}

type LarkChatSrv interface {
	RefreshAskGroup(ctx context.Context) error
}

var _ LarkChatSrv = (*LarkChatService)(nil)

func NewLarkChat(store store.Factory) *LarkChatService {
	return &LarkChatService{store: store}
}

const AskPingCatChatID = "oc_0e3ab5a9cdf06b40b1e86d190c0a0c4b"

type MemItem struct {
	MemberIdType string `json:"member_id_type"`
	MemberId     string `json:"member_id"`
	Name         string `json:"name"`
}

type MembersData struct {
	Items     []MemItem `json:"items"`
	PageToken string    `json:"page_token"`
	HasMore   bool      `json:"has_more"`
}

func (l *LarkChatService) RefreshAskGroup(ctx context.Context) error {
	log.L(ctx).Info("LarkChatSrv.RefreshAskGroup called")

	commonService := &LarkAPIService{store: l.store}

	mItems, err := getChatMembers(ctx, commonService, "")
	if err != nil {
		log.L(ctx).Error(err.Error())

		return errors.Wrap(err, "Error when get lark chat member bacause of the error in getChatMembers")
	}

	log.L(ctx).Info("success to get 'Ask PingCat' group members.")

	rStore := &rstorage.RedisCluster{
		KeyPrefix: rstore.AskPingCatChat,
	}

	if ok := rStore.DeleteScanMatch(rstore.AskPingCatChat + "*"); !ok {
		return errors.New("Can not delete old keys")
	}

	for _, it := range *mItems {
		_ = rStore.SetKey(it.MemberId, "y", 0)
	}

	log.L(ctx).Info("success to set 'Ask PingCat' group members in redis.")

	return nil
}

func getChatMembers(ctx context.Context, cs *LarkAPIService, pageToken string) (*[]MemItem, error) {
	var pageTokenQ string
	if pageToken != "" {
		pageTokenQ = "&page_token=" + pageToken
	}

	memsJsonRaw, err := cs.ReqLarkAPI(ctx, "GET", LarkOpenAPIBase+"/im/v1/chats/"+AskPingCatChatID+"/members?member_id_type=user_id&page_size=100"+pageTokenQ, nil, nil)
	if err != nil {
		log.Error(err.Error())

		return nil, errors.WithCode(code.ErrHttpRequest, "Error when request lark chat members api")
	}

	var d MembersData
	if err := json.Unmarshal(memsJsonRaw, &d); err != nil {
		log.Error(err.Error())

		return nil, errors.WithCode(code.ErrDecodingJSON, "Error when unmarshal lark get chat member res")
	}

	var result []MemItem
	result = append(result, d.Items...)
	if d.HasMore && d.PageToken != "" {
		mItems, err := getChatMembers(ctx, cs, d.PageToken)
		if err != nil {
			log.Error(err.Error())

			return nil, errors.Wrap(err, "Error when getChatMembers for next page")
		}
		result = append(result, *mItems...)
	}

	return &result, nil
}
