package k8s

import (
	"context"
	"crypto/tls"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/pingcap/log"
)

// http request with same endpoint
type HttpLink interface {
	Get(string) ([]byte, error)
	Post(string, interface{}) ([]byte, error)
}

// in one network
type HttpLinkNormal struct {
	ctx     context.Context
	baseURL string
	cli     *http.Client
}

// http client for normal link
func NewHTTPLinkNormal(ctx context.Context, scheme, ns, name, port string) HttpLink {

	return NewRawHTTPLinkNormal(ctx, fmt.Sprintf("%s://%s.%s:%s", scheme, name, ns, port))
}

func NewRawHTTPLinkNormal(ctx context.Context, baseURL string) *HttpLinkNormal {
	tr := &http.Transport{
		/* #nosec */
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	cli := &http.Client{Transport: tr}

	link := &HttpLinkNormal{
		ctx:     ctx,
		baseURL: baseURL,
		cli:     cli,
	}

	return link
}

func (g *HttpLinkNormal) Get(apiPath string) ([]byte, error) {

	taskURL, err := URLJoint(g.baseURL, apiPath)
	if err != nil {
		return nil, err
	}

	body, _, err := g.getHTTPResponseBody(http.MethodGet, taskURL, nil)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (g *HttpLinkNormal) Post(apiPath string, data interface{}) ([]byte, error) {
	taskURL, err := URLJoint(g.baseURL, apiPath)
	if err != nil {
		return nil, err
	}
	body, _, err := g.getHTTPResponseBody(http.MethodPost, taskURL, strings.NewReader(fmt.Sprint(data)))
	if err != nil {
		return nil, err
	}

	return body, nil
}

func (g *HttpLinkNormal) getHTTPResponseBody(method, urlStr string, body io.Reader) ([]byte, int, error) {
	req, err := http.NewRequestWithContext(g.ctx, method, urlStr, body)
	if err != nil {
		log.S().Errorf("http error %s,%s,%+v", urlStr, body, err)
		return nil, 0, err
	}
	resp, err := g.cli.Do(req)
	if err != nil {
		return nil, 0, err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.S().Errorf("http error %s,%s,%d,%s", urlStr, data, resp.StatusCode, err)
		return nil, resp.StatusCode, err
	}
	return data, resp.StatusCode, err
}
