package handler

import (
	"fmt"
	"net/http"
	"strings"
	"testing"
	"time"

	//"time"
	"github.com/gavv/httpexpect/v2"
	"github.com/imkira/go-interpol"
	"github.com/tidbcloud/qa-Gourd/common"
	"github.com/tidbcloud/qa-Gourd/util"
)

const (
	Status401 = 401
)

func DoRequest(t *testing.T, cs *common.GourdCase) {

	//create httpexpect instance

	var count int
	if cs.Retry != -2 { //-2 是csv文件中该case的retry为空时的默认值（无retry字段或者有retry字段，但此case的retry字段为空）
		count = cs.Retry
	} else {
		count = apiConfig.Retry
	}
	fmt.Println("retry num is ", count)
	for {
		reporter := httpexpect.NewAssertReporter(t)

		config := httpexpect.Config{
			BaseURL: apiConfig.BaseUrl, //必填
			//BaseURL:"https://api.apishop.net",
			//https://us-west-2.staging.shared.aws.tidbcloud.com json check
			//https://api.apishop.net plain phone
			RequestFactory: httpexpect.DefaultRequestFactory{},
			Client:         http.DefaultClient,
			Reporter:       reporter,
		}
		req := httpexpect.NewRequest(config, cs.Method, cs.Api)
		//path
		//fmt.Println("add path")
		for key, val := range cs.Paths {
			//fmt.Println(key + ":" + val)
			req.WithPath(key, val)
		}

		//param
		//fmt.Println("add param")
		var path_param string
		for key, val := range cs.Params {
			//fmt.Println(key + ":" + val)
			req.WithQuery(key, val)
			path_param += (key + "=" + val + "&")
		}

		// for digest auth
		// create a new digest authentication request
		if len(cs.DigestAuth) != 0 {
			path, _ := interpol.WithMap(cs.Api, cs.Paths)
			if path_param != "" {
				path_param = path_param[0 : len(path_param)-1]
				path = path + "?" + path_param
			}
			dr := util.NewRequest(cs.DigestAuth[0], cs.DigestAuth[1], cs.Method, apiConfig.BaseUrl+path, "")

			digestVal, err := dr.Execute()
			if err != nil {
				fmt.Printf("err in digest request is %v", err)
			}
			// set the auth header of req
			cs.Headers["authorization"] = digestVal
		}

		//header
		//fmt.Println("add header")
		for key, val := range cs.Headers { //不填的话（前面有逗号这里却没有值），Headers长度为0，就不会被处理
			if val != "" {
				//fmt.Println(key + ":" + val)
				fmt.Println("header is", key, val)
				req.WithHeader(key, val)
			}
			//填了空值
		}
		// use this param to saparate test case and user case (For billing)
		req.WithHeader("X-FUNCTION-TEST", "true")
		//body
		//fmt.Println("add body")
		if cs.Method != "GET" {
			//req.WithJSON(cs.Body)
			//var tb map[string]interface{}
			//tb = cs.Body
			//req.WithJSON(map[string]interface{}  )
			//fmt.Println("body is:", cs.Body)
			if cs.Body != "" {
				req.WithBytes([]byte(cs.Body))
			}
		}

		cs.Res = req.Expect()
		/*fmt.Println()
		fmt.Printf("do the request(%s), count is %d, the pathParam is %v, the Params is %v, the header is %v, the body is %s",
				cs.Desc, count, cs.Paths, cs.Params, cs.Headers, cs.Body)
		fmt.Println()*/
		if cs.Res.Raw().StatusCode == cs.Status || count == 0 {
			break
		} else {
			count--
			time.Sleep(time.Second * 5)
			content := cs.Res.Raw().Header.Get("Content-Type")
			t2 := strings.Split(content, ";") //text/plain; charset=utf-8

			switch t2[0] {
			case "application/json":
				// Bugfix 20230908 : 401 resp has content-type: application/json, however the body is not json format. This will cause err in cs.Res.JSON().Raw().
				if cs.Res.Raw().StatusCode == Status401 {
					fmt.Printf("method is %s, body is %s, resp is %s, csStatus is %v, X-Debug-Trace-Id:%s", cs.Method, cs.Body, cs.Res.Body(), cs.Status, cs.Res.Header("X-Debug-Trace-Id").Raw())
				} else {
					fmt.Printf("method is %s, body is %s, resp is %s, csStatus is %v, X-Debug-Trace-Id:%s", cs.Method, cs.Body, cs.Res.JSON().Raw(), cs.Status, cs.Res.Header("X-Debug-Trace-Id").Raw())
				}
				fmt.Println()
			default:
				fmt.Printf("method is %s, body is %v, resp is %s, csStatus is %v, X-Debug-Trace-Id:%s", cs.Method, cs.Body, cs.Res.Body(), cs.Status, cs.Res.Header("X-Debug-Trace-Id").Raw())
				fmt.Println()
			}
		}
	}
	//fmt.Println(cs.Res.JSON().Raw())
}
