package oracle

import (
	"context"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestSchemeHost(t *testing.T) {
	cases := []struct{ target, reqHost, wScheme, wHost string }{
		{"https://api.example.com/x", "", "https", "api.example.com"},
		{"http://t:8080/a?b=1", "", "http", "t:8080"},
		{"https://realhost.com/x", "placeholder", "https", "realhost.com"}, // target wins over spec Host
		{"", "only-host.com", "http", "only-host.com"},
	}
	for _, c := range cases {
		s, h := schemeHost(c.target, c.reqHost)
		if s != c.wScheme || h != c.wHost {
			t.Errorf("schemeHost(%q,%q) = %q,%q; want %q,%q", c.target, c.reqHost, s, h, c.wScheme, c.wHost)
		}
	}
}

func TestNormalizeCRLF(t *testing.T) {
	in := "GET / HTTP/1.1\nHost: t"
	out := normalizeCRLF(in)
	if !strings.HasSuffix(out, "\r\n\r\n") {
		t.Errorf("want trailing blank line, got %q", out)
	}
	if strings.Contains(strings.TrimSuffix(out, "\r\n\r\n"), "\n\n") {
		t.Error("should not double-blank")
	}
	if strings.Count(out, "\n") != strings.Count(out, "\r\n") {
		t.Error("every LF should be CRLF")
	}
}

func TestSendRaw_AgainstTestServer(t *testing.T) {
	var gotPath, gotHdr, gotBody, gotMethod string
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		gotPath = r.URL.RequestURI()
		gotHdr = r.Header.Get("X-Probe")
		gotMethod = r.Method
		b, _ := io.ReadAll(r.Body)
		gotBody = string(b)
		w.WriteHeader(201)
		_, _ = w.Write([]byte("hello-body"))
	}))
	defer srv.Close()

	raw := "POST /api?id=7 HTTP/1.1\nHost: placeholder\nX-Probe: yes\nContent-Type: text/plain\n\npayload-here"
	status, body, lat, err := sendRaw(context.Background(), srv.Client(), srv.URL, raw)
	if err != nil {
		t.Fatalf("sendRaw: %v", err)
	}
	if status != 201 || body != "hello-body" {
		t.Errorf("status=%d body=%q", status, body)
	}
	if lat <= 0 {
		t.Error("latency should be measured")
	}
	if gotMethod != "POST" || gotPath != "/api?id=7" || gotHdr != "yes" || gotBody != "payload-here" {
		t.Errorf("server saw method=%q path=%q hdr=%q body=%q", gotMethod, gotPath, gotHdr, gotBody)
	}
}

func TestParseRaw_NoHostErrors(t *testing.T) {
	_, err := parseRaw(context.Background(), "", "GET /x HTTP/1.1\n\n")
	if err == nil {
		t.Error("expected error when neither target nor Host provides a host")
	}
}

func TestParseRaw_MalformedErrors(t *testing.T) {
	_, err := parseRaw(context.Background(), "http://t", "not a request")
	if err == nil {
		t.Error("expected parse error on garbage")
	}
}
