/*
 * 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 http

import (
	"bytes"
	"context"
	"io/ioutil"
	"net/http"
	"testing"
)

import (
	"github.com/dubbogo/dubbo-go-pixiu-filter/pkg/api/config"
	"github.com/stretchr/testify/assert"
)

import (
	"github.com/apache/dubbo-go-pixiu/pkg/client"
	"github.com/apache/dubbo-go-pixiu/pkg/common/mock"
)

func TestMapParams(t *testing.T) {
	hClient := NewHTTPClient()
	r, _ := http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte(
		"{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}")))
	r.Header.Set("Auth", "12345")
	api := mock.GetMockAPI(config.MethodGet, "/mock/test")
	req := client.NewReq(context.TODO(), r, api)

	val, err := hClient.MapParams(req)
	assert.Nil(t, err)
	p, _ := val.(*requestParams)
	assert.Equal(t, p.Query.Encode(), "team=theBoys")
	assert.Equal(t, p.Header.Get("Auth"), "12345")
	rawBody, err := ioutil.ReadAll(p.Body)
	assert.Nil(t, err)
	assert.Equal(t, string(rawBody),
		"{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}")

	api.IntegrationRequest.MappingParams = []config.MappingParam{
		{
			Name:  "queryStrings.team",
			MapTo: "queryStrings.team",
		},
		{
			Name:  "requestBody.id",
			MapTo: "headers.Id",
		},
		{
			Name:  "headers.Auth",
			MapTo: "queryStrings.auth",
		},
		{
			Name:  "requestBody.age",
			MapTo: "requestBody.age",
		},
		{
			Name:  "requestBody.testStruct",
			MapTo: "requestBody.testStruct",
		},
		{
			Name:  "requestBody.testStruct.nickName",
			MapTo: "requestBody.nickName",
		},
	}
	api.IntegrationRequest.HTTPBackendConfig.Schema = "https"
	api.IntegrationRequest.HTTPBackendConfig.Host = "localhost"
	r, _ = http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte(
		"{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}")))
	r.Header.Set("Auth", "12345")
	req = client.NewReq(context.TODO(), r, api)
	val, err = hClient.MapParams(req)
	assert.Nil(t, err)
	p, _ = val.(*requestParams)
	assert.Equal(t, p.Header.Get("Id"), "12345")
	assert.Equal(t, p.Query.Get("auth"), "12345")
	assert.Equal(t, p.Query.Get("team"), "theBoys")
	rawBody, err = ioutil.ReadAll(p.Body)
	assert.Nil(t, err)
	assert.Equal(t, string(rawBody),
		"{\"age\":\"19\",\"nickName\":\"trump\",\"testStruct\":{\"name\":\"mock\",\"nickName\":\"trump\",\"test\":\"happy\"}}")
}

func TestParseURL(t *testing.T) {
	hClient := NewHTTPClient()
	requestParams := newRequestParams()
	requestParams.URIParams.Set("id", "12345")
	r, _ := http.NewRequest("POST", "/mock/test/12345", bytes.NewReader([]byte("")))
	api := mock.GetMockAPI(config.MethodGet, "/mock/test/:id")
	api.IntegrationRequest.RequestType = "http"
	api.IntegrationRequest.HTTPBackendConfig.Schema = "http"
	api.IntegrationRequest.HTTPBackendConfig.Host = "abc.com"
	api.IntegrationRequest.HTTPBackendConfig.Path = "/:id"
	req := client.NewReq(context.TODO(), r, api)
	parsedURL, err := hClient.parseURL(req, *requestParams)
	assert.Equal(t, parsedURL, "http://abc.com/12345")
	assert.Nil(t, err)

	requestParams = newRequestParams()
	requestParams.URIParams.Set("id", "12345")
	requestParams.Query.Set("name", "Joe")
	parsedURL, err = hClient.parseURL(req, *requestParams)
	assert.Equal(t, parsedURL, "http://abc.com/12345?name=Joe")
	assert.Nil(t, err)

	requestParams = newRequestParams()
	requestParams.URIParams.Set("id", "12345")
	req.API.HTTPBackendConfig.Path = ""
	parsedURL, err = hClient.parseURL(req, *requestParams)
	assert.Equal(t, parsedURL, "http://abc.com")
	assert.Nil(t, err)

	requestParams = newRequestParams()
	requestParams.URIParams.Set("id", "12345")
	requestParams.Query.Set("name", "Joe")
	parsedURL, err = hClient.parseURL(req, *requestParams)
	assert.Equal(t, parsedURL, "http://abc.com?name=Joe")
	assert.Nil(t, err)
}
