// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main_test

import (
	"io"
	"net/http"
	"strconv"
	"testing"

	catapult "go.fuchsia.dev/infra/cmd/catapult"
)

func TestCreateUploadRequest(t *testing.T) {
	t.Run("URL looks like scheme://host[:port]", func(t *testing.T) {
		expectCreationSuccess(
			"https://chromeperf.appspot.com:443",
			"https://chromeperf.appspot.com:443/add_histograms",
			t)
		expectCreationSuccess(
			"https://chromeperf.appspot.com:443/",
			"https://chromeperf.appspot.com:443/add_histograms",
			t)
		expectCreationSuccess(
			"https://chromeperf.appspot.com/",
			"https://chromeperf.appspot.com/add_histograms",
			t)
		expectCreationSuccess(
			"https://chromeperf.appspot.com",
			"https://chromeperf.appspot.com/add_histograms",
			t)
		expectCreationSuccess(
			"http://chromeperf.appspot.com",
			"http://chromeperf.appspot.com/add_histograms",
			t)
		expectCreationSuccess(
			"hello://weird.scheme.com",
			"hello://weird.scheme.com/add_histograms",
			t)
	})

	t.Run("URL does not look like scheme://host[:port]", func(t *testing.T) {
		expectCreationFailure("https://chromeperf.appspot.com/#fragment", t)
		expectCreationFailure("https://chromeperf.appspot.com:443?arg=foo", t)
		expectCreationFailure("https://chromeperf.appspot.com:80/non_root_path.html", t)
		expectCreationFailure("https://chromeperf.appspot.com:443/non_root_path.html?args=also#fragmnent-too", t)
	})
}

func expectCreationFailure(inputURL string, t *testing.T) {
	content := "{'foo': 'bar123abc'}"
	_, err := catapult.CreateUploadRequest(inputURL, content)
	if err == nil {
		t.Fatalf("Expected an error. Got nil when given %q", inputURL)
	}
}

func expectCreationSuccess(inputURL string, expectedURL string, t *testing.T) {
	content := "{'foo': 'bar123abc'}"
	req, err := catapult.CreateUploadRequest(inputURL, content)
	if err != nil {
		t.Fatal(err)
	}

	actualURL := req.URL.String()
	if actualURL != expectedURL {
		t.Errorf("expected URL %s. Got %s", expectedURL, actualURL)
	}

	if req.Method != http.MethodPost {
		t.Errorf("expected method %s. Got %s", http.MethodPost, req.Method)
	}

	userAgent := req.Header.Get("User-Agent")
	if userAgent != catapult.FuchsiaUserAgent {
		t.Errorf("expected User-Agent: %s. Got %s", catapult.FuchsiaUserAgent, userAgent)
	}

	expectedContentType := "application/x-www-form-urlencoded"
	contentType := req.Header.Get("Content-Type")
	if contentType != expectedContentType {
		t.Errorf("expected Content-Type: %s. Got %s", expectedContentType, contentType)
	}

	contentLength, err := strconv.ParseInt(req.Header.Get("Content-Length"), 10, 64)
	if err != nil {
		t.Error("failed to parse Content-Length", err)
	}
	actualContent, err := io.ReadAll(req.Body)
	if err != nil {
		t.Error("failed to read request body", err)
	}
	expectedContentLength := int64(len(actualContent))
	if contentLength != expectedContentLength {
		t.Errorf("expected Content-Length %d for %s. Got %d",
			expectedContentLength, actualContent, contentLength)
	}
}
