package tool

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"time"

	"github.com/opentracing/opentracing-go"
	"google.golang.org/grpc/metadata"
)

// PostWithHeaders 自定义header参数的post请求
// url：         请求地址
// data：        POST请求提交的数据
// headers： 请求头 key-value 的 map
// timeoutSecond： 超时时长，单位秒
func PostWithHeaders(url string, data interface{}, headers map[string]string, timeoutSecond int32) ([]byte, error) {
	// 实例化 client 对象
	client := &http.Client{Timeout: time.Duration(timeoutSecond) * time.Second}

	// 根据 method、url、body 实例化 req 对象
	jsonStr, _ := json.Marshal(data)
	body := bytes.NewBuffer(jsonStr)
	req, errNewRequest := http.NewRequest("POST", url, body)
	if errNewRequest != nil {
		return make([]byte, 0), errNewRequest
	}

	// 设置 req 的 header
	for headerKey, headerValue := range headers {
		req.Header.Set(headerKey, headerValue)
	}

	// 客户端发出请求
	resp, errClientDo := client.Do(req)
	if errClientDo != nil {
		return make([]byte, 0), errClientDo
	}

	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	return io.ReadAll(resp.Body)
}

// 发送POST请求
// url：         请求地址
// data：        POST请求提交的数据
// contentType： 请求体格式，如：application/json
func Post(url string, data interface{}, contentType string) string {

	// 超时时间：5秒
	client := &http.Client{Timeout: 5 * time.Second}
	jsonStr, _ := json.Marshal(data)
	resp, err := client.Post(url, contentType, bytes.NewBuffer(jsonStr))
	if err != nil {
		return ""
		// panic(err)
	}
	defer resp.Body.Close()

	result, _ := ioutil.ReadAll(resp.Body)
	return string(result)
}

// 发送GET请求
// url：         请求地址
func Get(url string) string {
	// 超时时间：5秒
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return ""
		// panic(err)
	}
	defer resp.Body.Close()
	var buffer [512]byte
	result := bytes.NewBuffer(nil)
	for {
		n, err := resp.Body.Read(buffer[0:])
		result.Write(buffer[0:n])
		if err != nil && err == io.EOF {
			break
		} else if err != nil {
			panic(err)
		}
	}

	return result.String()
}

func GetServiceAddress(serviceS, port string) string {
	srvAdd := ""
	releaseS := os.Getenv("release")
	if releaseS == "v2" || releaseS == "test" || releaseS == "develop" { // 正式服 需要认证
		// serviceS := os.Getenv("service")
		srvAdd = serviceS + ".baidu.com:80" // 这个可以根据服务掉的
	} else {
		srvAdd = "0.0.0.0:" + port
	}

	return srvAdd
}

// 获取本地的ip
func GetLocalIp() (string, error) {

	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", err
	}

	for _, addr := range addrs {
		if ipNet, ok := addr.(*net.IPNet); ok {
			if ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil && ipNet.IP.IsGlobalUnicast() && ipNet.IP.IsPrivate() {
				return ipNet.IP.String(), nil
			}
		}
	}

	return "", nil
}

// CORs 跨域处理
func CORs(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		allowHeaders := r.Header.Get(`Access-Control-Request-Headers`)
		if allowHeaders != `` {
			allowHeaders = `,` + allowHeaders
		}

		w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
		w.Header().Set("Access-Control-Allow-Methods", "GET, PUT, POST, PATCH, DELETE")
		w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, ResponseType"+allowHeaders)

		if r.Method == "OPTIONS" {
			return
		}

		h.ServeHTTP(w, r)
	})
}

// GetXForwardedFor gRPC里面获取http的客户端请求地址
func GetXForwardedFor(ctx context.Context) []string {
	if md, ok := metadata.FromIncomingContext(ctx); ok {
		return md.Get("x-forwarded-for")
	}
	return nil
}

// HttpInterceptor HTTP中间件
func HttpInterceptor(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodOptions {
			w.WriteHeader(http.StatusOK)
			return
		}

		// 设置超时白名单
		if InArray(r.URL.Path, []string{
			"/infoflow/my-doc/hk-plan-edit",                 // 提交赴港计划书
			"/infoflow/certificate/certificate_to_pdf",      //生成pdf
			"/infoflow/order-information/get_id_card",       //身份证识别
			"/infoflow/order-information/get_hk_macao_pass", //港澳通行证识别
			"/infoflow/work/getOcrFileContent",
			"/infoflow/my-doc/get_temporaryUrl",         //获取腾讯文档临时链接
			"/infoflow/my-doc/doc-submit",               // 腾讯文档提交时长
			"/infoflow/order/information/submit",        //提交信息完善订单时间
			"/infoflow/sign/creat-contract",             //创建合同
			"/infoflow/sign/sign-callback",              //签字文件回调
			"/marketing/crm/backend/case/generate-code", //生成案例库的海报图
		}) {
			r.Header.Set(`Grpc-Timeout`, "60S")
		}
		var (
			revision string
			systemOs string
		)
		revision = r.Header.Get("revision")
		r.Header.Set(`revision`, revision)
		r.Header.Set(`systemOs`, systemOs)
		if os.Getenv("ENVIRONMENT") != "LOCAL" {
			ctx := r.Context()
			if _, ok := ctx.Deadline(); !ok {
				var cancel context.CancelFunc
				ctx, cancel = context.WithTimeout(ctx, time.Second*5)
				defer cancel()
			}
		}
		rootSpan, ctx := opentracing.StartSpanFromContext(
			r.Context(),
			fmt.Sprintf(`%s:%s`, r.Method, r.URL.Path),
		)
		// r.Header.Set(runtime.MetadataHeaderPrefix+`uber-trace-id`, r.Header.Get(`uber-trace-id`))
		rootSpan.SetTag(`http.url`, r.URL.Path)
		rootSpan.SetTag(`http.method`, r.Method)
		rootSpan.SetTag(`http.host`, r.Host)
		rootSpan.SetTag(`http.user_agent`, r.UserAgent())
		rootSpan.SetTag(`http.revision`, revision)
		rootSpan.SetTag(`remote_addr`, r.RemoteAddr)
		defer rootSpan.Finish()
		h.ServeHTTP(w, r.WithContext(ctx))
	})
}
