package scrape

import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"testing"
)

func TestClassifyStatusCodes(t *testing.T) {
	cases := []struct {
		status int
		want   FailureKind
	}{
		{200, FailureNone},
		{201, FailureNone},
		{301, FailureStructural},
		{400, FailureStructural},
		{401, FailureAuth},
		{403, FailureAuth},
		{404, FailureStructural},
		{429, FailureRateLimit},
		{500, FailureNetwork},
		{502, FailureNetwork},
		{503, FailureNetwork},
	}
	for _, tc := range cases {
		t.Run(fmt.Sprintf("status=%d", tc.status), func(t *testing.T) {
			got := Classify(&http.Response{StatusCode: tc.status}, nil, nil)
			if got != tc.want {
				t.Errorf("status %d: got %q, want %q", tc.status, got, tc.want)
			}
		})
	}
}

func TestClassifyNetworkError(t *testing.T) {
	// A wrapped net.OpError (typical from net/http on dial failure).
	netErr := &net.OpError{Op: "dial", Err: errors.New("connection refused")}
	if got := Classify(nil, netErr, nil); got != FailureNetwork {
		t.Errorf("net.OpError: got %q, want %q", got, FailureNetwork)
	}
}

func TestClassifyLooksLikeLoginPage(t *testing.T) {
	body := []byte(`<html><body><form action="/login.php" method="post">` +
		`<input name="password" type="password"></form></body></html>`)
	got := Classify(&http.Response{StatusCode: 200}, nil, body)
	if got != FailureAuth {
		t.Errorf("login-page heuristic: got %q, want %q", got, FailureAuth)
	}
}

func TestClassifyHonest200(t *testing.T) {
	body := []byte(`{"uploaded": 12345}`)
	got := Classify(&http.Response{StatusCode: 200}, nil, body)
	if got != FailureNone {
		t.Errorf("honest 200: got %q, want %q", got, FailureNone)
	}
}

func TestEventLevel(t *testing.T) {
	cases := []struct {
		kind FailureKind
		want string
	}{
		{FailureAuth, "error"},
		{FailureStructural, "error"},
		{FailureRateLimit, "warn"},
		{FailureNetwork, "info"},
		{FailureNone, "info"},
	}
	for _, tc := range cases {
		if got := tc.kind.EventLevel(); got != tc.want {
			t.Errorf("%q.EventLevel() = %q, want %q", tc.kind, got, tc.want)
		}
	}
}
