/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package tools

import (
	"github.com/gavv/httpexpect/v2"
	"github.com/onsi/ginkgo"
	"net/http"
	"strings"
	"time"
)

var (
	token  = "edd1c9f034335f136f87ad84b625c8f1"
	A6_CP_Host = "http://127.0.0.1:9180"
	A6_DP_Host = "http://127.0.0.1:9080"
)

func GetAdminToken() string {
	return token
}

func PutA6Conf() *httpexpect.Expect {
	t := ginkgo.GinkgoT()
	return httpexpect.New(t, A6_CP_Host)
}

func GetA6Expect() *httpexpect.Expect {
	t := ginkgo.GinkgoT()
	return httpexpect.New(t, A6_DP_Host)
}

type HttpTestCase struct {
	Object            *httpexpect.Expect
	Method            string
	Path              string
	Query             string
	Body              string
	Headers           map[string]string
	ExpectStatus      int
	ExpectStatusRange httpexpect.StatusRange
	ExpectCode        int
	ExpectBody        interface{}
	ExpectHeaders     map[string]string
	Sleep             time.Duration //ms
}

func RunTestCase(htc HttpTestCase) {
	var req *httpexpect.Request
	expect := htc.Object
	switch htc.Method {
	case http.MethodGet:
		req = expect.GET(htc.Path)
	case http.MethodPost:
		req = expect.POST(htc.Path)
	case http.MethodPut:
		req = expect.PUT(htc.Path)
	case http.MethodDelete:
		req = expect.DELETE(htc.Path)
	case http.MethodOptions:
		req = expect.OPTIONS(htc.Path)
	default:
	}

	if req == nil {
		panic("init request failed")
	}

	if htc.Sleep == 0 {
		time.Sleep(time.Duration(100) * time.Millisecond)
	} else {
		time.Sleep(htc.Sleep)
	}

	if len(htc.Query) > 0 {
		req.WithQueryString(htc.Query)
	}

	setContentType := false
	for hk, hv := range htc.Headers {
		req.WithHeader(hk, hv)
		if strings.ToLower(hk) == "content-type" {
			setContentType = true
		}
	}

	if !setContentType {
		req.WithHeader("Content-Type", "application/json")
	}

	if len(htc.Body) > 0 {
		req.WithText(htc.Body)
	}

	resp := req.Expect()

	if htc.ExpectStatus != 0 {
		resp.Status(htc.ExpectStatus)
	}

	if htc.ExpectStatusRange > 0 {
		resp.StatusRange(htc.ExpectStatusRange)
	}

	if htc.ExpectHeaders != nil {
		for hk, hv := range htc.ExpectHeaders {
			resp.Header(hk).Equal(hv)
		}
	}

	if htc.ExpectBody != nil {
		if body, ok := htc.ExpectBody.(string); ok {
			if len(body) == 0 {
				resp.Body().Empty()
			} else {
				resp.Body().Contains(body)
			}
		}

		if bodies, ok := htc.ExpectBody.([]string); ok && len(bodies) > 0 {
			for _, b := range bodies {
				resp.Body().Contains(b)
			}
		}
	}
}
