package feishu

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	lark "github.com/larksuite/oapi-sdk-go/v3"
	larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
	larkauth "github.com/larksuite/oapi-sdk-go/v3/service/auth/v3"
	"github.com/patrickmn/go-cache"
	"github.com/sirupsen/logrus"
	"net/http"
	"os"
	"time"
)

var tokenCache *cache.Cache
var tokenCacheKey = "feishuTenantAccessToken"
var appId, appSecret string

var LarkClient *lark.Client

func InitFeiShuClient() {
	appId = os.Getenv("APP_ID")
	appSecret = os.Getenv("APP_SECRET")

	fmt.Println("init feishu client", appId, appSecret)
	LarkClient = lark.NewClient(appId, appSecret, // 默认配置为自建应用
		// lark.WithMarketplaceApp(), // 可设置为商店应用
		lark.WithLogLevel(larkcore.LogLevelDebug),
		lark.WithReqTimeout(3*time.Second),
		lark.WithEnableTokenCache(true),
		lark.WithHelpdeskCredential("id", "token"),
		lark.WithHttpClient(http.DefaultClient),
	)
	tokenCache = cache.New(10*time.Minute, 10*time.Minute)
}

// 获取TenantAccessToken
func GetTenantAccessToken() (string, error) {
	if token, ok := tokenCache.Get(tokenCacheKey); ok && token.(string) != "" {
		return token.(string), nil
	}
	// 创建请求对象
	req := larkauth.NewInternalTenantAccessTokenReqBuilder().
		Body(larkauth.NewInternalTenantAccessTokenReqBodyBuilder().
			AppId(appId).
			AppSecret(appSecret).
			Build()).
		Build()

	// 发起请求
	resp, err := LarkClient.Auth.V3.TenantAccessToken.Internal(context.Background(), req)

	// 处理错误
	if err != nil {
		logrus.Warnf("GetTenantAccessToken error: %v", err)
		return "", err
	}

	// 服务端错误处理
	if !resp.Success() {
		logrus.Warnf("GetTenantAccessToken error: %v", resp.Msg)
		return "", errors.New(resp.Msg)
	}
	type tokenResp struct {
		Code              int    `json:"code"`
		Expire            int    `json:"expire"`
		Msg               string `json:"msg"`
		TenantAccessToken string `json:"tenant_access_token"`
	}
	respData := new(tokenResp)
	err = json.Unmarshal(resp.RawBody, respData)
	if err != nil {
		logrus.Warnf("GetTenantAccessToken error: %v", err)
		return "", err
	}
	tokenCache.Set(tokenCacheKey, respData.TenantAccessToken, time.Duration(respData.Expire)*time.Second)
	return respData.TenantAccessToken, nil
}
