package octopusHttp

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"github.com/go-resty/resty/v2"
	"time"
)

const (
	GetToken = "api/v1/token"
)

type TokenModel struct {
	Code int    `json:"code"`
	Data string `json:"data"`
	Msg  string `json:"msg"`
}

type TokenTimePair struct {
	Token     string
	ExpiredAt time.Time
}

type Login struct {
	Username string `json:"user"`
	Password string `json:"pwd"`
}

type Token struct {
	server   string
	host     string
	user     string
	pwd      string
	tokenUrl string
	ttp      *TokenTimePair
	token    string
}

func NewToken(server, host, user, pwd string) (*Token, error) {
	login := Login{
		Username: user,
		Password: pwd,
	}
	jsonStr, _ := json.Marshal(login)
	tokenUrl := server + GetToken

	token, err := generateToken(jsonStr, tokenUrl, host)
	if err != nil {
		return &Token{token: "", host: host, user: user, pwd: pwd, tokenUrl: tokenUrl}, err
	}
	return &Token{token: token, host: host, user: user, pwd: pwd, tokenUrl: tokenUrl}, nil
}

func (t *Token) Get() (string, error) {
	if t.token == "" {
		err := t.Update()
		if err != nil {
			return "", errors.New("get token failed")
		}
	}
	return t.token, nil
}

func (t *Token) Update() error {
	login := Login{
		Username: t.user,
		Password: t.pwd,
	}
	jsonStr, _ := json.Marshal(login)
	tokenUrl := t.server + GetToken
	token, err := generateToken(jsonStr, tokenUrl, t.host)
	if err != nil {
		return errors.New("get token failed")
	}

	t.token = token
	return nil
}

func generateToken(jsonStr []byte, tokenUrl string, host string) (string, error) {
	client := resty.New().SetTimeout(time.Duration(5) * time.Second)
	req := client.R()

	var tokenResp TokenModel

	client.SetTLSClientConfig(&tls.Config{
		InsecureSkipVerify: true,
	})

	_, err := req.
		SetResult(&tokenResp).
		SetHeader("Content-Type", "application/json").
		SetQueryString("addr=" + host).
		SetBody(jsonStr).
		Post(tokenUrl)
	if err != nil {
		return "", err
	}

	return tokenResp.Data, nil
}
