package lark

import (
	"context"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/spf13/viper"

	"github.com/pingcap-inc/it-automation/internal/pkg/redis"
)

// APIPath
var (
	TenantAccessTokenURL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
)

const (
	prefix   = "lark"
	tokenInR = "tokenInR"
)

// GetTenantAccessToken get tenant access tokenInR for app
// Refer to: https://open.feishu.cn/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/auth-v3/auth/tenant_access_token_internal
func GetTenantAccessToken(ctx context.Context) string {
	cli := &http.Client{}
	restore := &redis.Redis{}
	key, err := restore.GetRedis(prefix).GetKey(tokenInR)
	if err != nil {
		if err.Error() != "key not found" {
			log.Errorf("Error when get tokenInR from redis: %v", err)
			return ""
		}
	}
	if key != "" {
		return key
	}

	reqBody := TenantAccessTokenRequest{
		APPID:     viper.GetString("lark.id"),
		APPSecret: viper.GetString("lark.secret"),
	}
	reqBytes, err := json.Marshal(reqBody)
	if err != nil {
		return ""
	}

	req, err := http.NewRequest("POST", TenantAccessTokenURL, strings.NewReader(string(reqBytes)))
	if err != nil {
		return ""
	}
	resp, err := cli.Do(req)
	if err != nil {
		log.WithError(err).Errorf("failed to get tokenInR")

		return ""
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}
	tokenResp := &TenantAccessTokenResponse{}
	err = json.Unmarshal(body, tokenResp)
	if err != nil {
		return ""
	}

	err = restore.GetRedis(prefix).SetKey(tokenInR, tokenResp.TenantAccessToken, 20*time.Minute)
	if err != nil {
		log.Errorf("Error when set tokenInR to redis: %v", err)

		return ""
	}

	return tokenResp.TenantAccessToken
}
