package httpclient

import (
	"bytes"
	"context"
	"encoding/json"
	"git.nspix.com/golang/micro/helper/random"
	"io"
	"net"
	"net/http"
	"strings"
	"time"
)

var (
	httpClient = http.Client{
		Timeout: time.Second * 15,
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).DialContext,
			ForceAttemptHTTP2:     false,
			MaxIdleConns:          10,
			IdleConnTimeout:       30 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
		},
	}
)

func Get(ctx context.Context, url string, header map[string]string) (res *http.Response, err error) {
	var (
		req *http.Request
	)
	if req, err = http.NewRequest("GET", url, nil); err != nil {
		return
	}
	if header != nil {
		for k, v := range header {
			req.Header.Set(k, v)
		}
	}
	return MockDo(ctx, req)
}

func Post(ctx context.Context, url string, header map[string]string, data interface{}) (res *http.Response, err error) {
	var (
		req         *http.Request
		contentType string
		reader      io.Reader
	)
	switch v := data.(type) {
	case string:
		reader = strings.NewReader(v)
		contentType = "x-www-form-urlencoded"
	case []byte:
		reader = bytes.NewReader(v)
		contentType = ""
	default:
		var b []byte
		if b, err = json.Marshal(v); err == nil {
			reader = bytes.NewReader(b)
			contentType = "application/json"
		} else {
			return
		}
	}
	if req, err = http.NewRequest("POST", url, reader); err != nil {
		return
	}
	if contentType != "" {
		req.Header.Set("Content-Type", contentType)
	}
	if header != nil {
		for k, v := range header {
			req.Header.Set(k, v)
		}
	}
	return MockDo(ctx, req)
}

func MockDo(ctx context.Context, req *http.Request) (res *http.Response, err error) {
	randomIp := random.IP()
	req.Header.Set("X-Forwarded-For", randomIp)
	req.Header.Set("X-Real-IP", randomIp)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36")
	if ctx != nil {
		req = req.WithContext(ctx)
	}
	return Do(ctx, req)
}

func Do(ctx context.Context, req *http.Request) (res *http.Response, err error) {
	if ctx != nil {
		req = req.WithContext(ctx)
	}
	return httpClient.Do(req)
}
