// Copyright 2017 The Go 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 perfdata

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"golang.org/x/build/internal/diff"
	"golang.org/x/perf/storage/benchfmt"
)

func TestQueryError(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "invalid query", 500)
	}))
	defer ts.Close()

	c := &Client{BaseURL: ts.URL}

	s, err := c.Query(context.Background(), "invalid query")
	if err == nil {
		s.Close()
		t.Error("Err = nil, want error")
	}
}

func TestQuery(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if have, want := r.URL.RequestURI(), "/search?q=key1%3Avalue+key2%3Avalue"; have != want {
			t.Errorf("RequestURI = %q, want %q", have, want)
		}
		fmt.Fprintf(w, "key: value\nBenchmarkOne 5 ns/op\nkey: value2\nBenchmarkTwo 10 ns/op\n")
	}))
	defer ts.Close()

	c := &Client{BaseURL: ts.URL}

	s, err := c.Query(context.Background(), "key1:value key2:value")
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	defer s.Close()
	q := benchfmt.NewReader(s)

	var buf bytes.Buffer
	bp := benchfmt.NewPrinter(&buf)

	for q.Next() {
		if err := bp.Print(q.Result()); err != nil {
			t.Fatalf("Print: %v", err)
		}
	}
	if err := q.Err(); err != nil {
		t.Fatalf("Err: %v", err)
	}
	want := "key: value\nBenchmarkOne 5 ns/op\nkey: value2\nBenchmarkTwo 10 ns/op\n"
	if diff := diff.Diff("have", buf.Bytes(), "want", []byte(want)); diff != nil {
		t.Errorf("wrong results:\n%s", diff)
	}
}

func TestListUploads(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if have, want := r.URL.RequestURI(), "/uploads?extra_label=key1&extra_label=key2&limit=10&q=key1%3Avalue+key2%3Avalue"; have != want {
			t.Errorf("RequestURI = %q, want %q", have, want)
		}
		fmt.Fprintf(w, "%s\n", `{"UploadID": "id", "Count": 100, "LabelValues": {"key1": "value"}}`)
	}))
	defer ts.Close()

	c := &Client{BaseURL: ts.URL}

	r := c.ListUploads(context.Background(), "key1:value key2:value", []string{"key1", "key2"}, 10)
	defer r.Close()

	if !r.Next() {
		t.Errorf("Next = false, want true")
	}
	if have, want := r.Info(), (UploadInfo{Count: 100, UploadID: "id", LabelValues: benchfmt.Labels{"key1": "value"}}); !reflect.DeepEqual(have, want) {
		t.Errorf("Info = %#v, want %#v", have, want)
	}
	if err := r.Err(); err != nil {
		t.Fatalf("Err: %v", err)
	}
}

func TestNewUpload(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if have, want := r.URL.RequestURI(), "/upload"; have != want {
			t.Errorf("RequestURI = %q, want %q", have, want)
		}
		mr, err := r.MultipartReader()
		if err != nil {
			t.Error(err)
		}
		i := 0
		for i = 0; ; i++ {
			p, err := mr.NextPart()
			if err == io.EOF {
				break
			}
			name := p.FormName()
			if name == "commit" {
				continue
			}
			if name != "file" {
				t.Errorf("unexpected field %q, want file", name)
			}
			if have, want := p.FileName(), fmt.Sprintf("want%d.txt", i); have != want {
				t.Errorf("file name = %q, want %q", have, want)
			}
			content, _ := io.ReadAll(p)
			if have, want := string(content), "content"; have != want {
				t.Errorf("unexpected content %q, want %q", have, want)
			}
		}
		if i != 3 {
			t.Errorf("number of files = %d, want %d", i, 3)
		}
		fmt.Fprintf(w, "%s\n", `{"uploadid": "id", "fileids": ["id/1", "id/2"]}`)
	}))
	defer ts.Close()

	c := &Client{BaseURL: ts.URL}

	u := c.NewUpload(context.Background())
	for i := 0; i < 2; i++ {
		w, err := u.CreateFile(fmt.Sprintf("want%d.txt", i))
		if err != nil {
			t.Fatalf("CreateFile = %v", err)
		}
		if _, err := fmt.Fprintf(w, "content"); err != nil {
			t.Fatalf("Write returned %v", err)
		}
	}
	status, err := u.Commit()
	if err != nil {
		t.Errorf("Commit = %v", err)
	}
	if status.UploadID != "id" {
		t.Errorf("status.UploadID = %q, want %q", status.UploadID, "id")
	}
}

func TestNewUploadAbort(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if have, want := r.URL.RequestURI(), "/upload"; have != want {
			t.Errorf("RequestURI = %q, want %q", have, want)
		}
		mr, err := r.MultipartReader()
		if err != nil {
			t.Error(err)
		}
		i := 0
		for i = 0; ; i++ {
			p, err := mr.NextPart()
			if err == io.EOF {
				break
			}
			name := p.FormName()
			if name == "abort" {
				continue
			}
			if name != "file" {
				t.Errorf("unexpected field %q, want file or abort", name)
			}
			if have, want := p.FileName(), fmt.Sprintf("want%d.txt", i); have != want {
				t.Errorf("file name = %q, want %q", have, want)
			}
			content, _ := io.ReadAll(p)
			if have, want := string(content), "content"; have != want {
				t.Errorf("unexpected content %q, want %q", have, want)
			}
		}
		if i != 3 {
			t.Errorf("number of files = %d, want %d", i, 3)
		}
		fmt.Fprintf(w, "%s\n", `{"uploadid": "id", "fileids": ["id/1", "id/2"]}`)
	}))
	defer ts.Close()

	c := &Client{BaseURL: ts.URL}

	u := c.NewUpload(context.Background())
	for i := 0; i < 2; i++ {
		w, err := u.CreateFile(fmt.Sprintf("want%d.txt", i))
		if err != nil {
			t.Fatalf("CreateFile = %v", err)
		}
		if _, err := fmt.Fprintf(w, "content"); err != nil {
			t.Fatalf("Write returned %v", err)
		}
	}
	if err := u.Abort(); err != nil {
		t.Errorf("Abort = %v", err)
	}
}
