package httpmw_test

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/coder/coder/v2/coderd/httpmw"
)

func TestHSTS(t *testing.T) {
	t.Parallel()

	tests := []struct {
		Name    string
		MaxAge  int
		Options []string

		wantErr      bool
		expectHeader string
	}{
		{
			Name:    "Empty",
			MaxAge:  0,
			Options: nil,
		},
		{
			Name:    "NoAge",
			MaxAge:  0,
			Options: []string{"includeSubDomains"},
		},
		{
			Name:    "NegativeAge",
			MaxAge:  -100,
			Options: []string{"includeSubDomains"},
		},
		{
			Name:         "Age",
			MaxAge:       1000,
			Options:      []string{},
			expectHeader: "max-age=1000",
		},
		{
			Name:   "AgeSubDomains",
			MaxAge: 1000,
			// Mess with casing
			Options:      []string{"INCLUDESUBDOMAINS"},
			expectHeader: "max-age=1000; includeSubDomains",
		},
		{
			Name:         "AgePreload",
			MaxAge:       1000,
			Options:      []string{"Preload"},
			expectHeader: "max-age=1000; preload",
		},
		{
			Name:         "AllOptions",
			MaxAge:       1000,
			Options:      []string{"preload", "includeSubDomains"},
			expectHeader: "max-age=1000; preload; includeSubDomains",
		},

		// Error values
		{
			Name:    "BadOption",
			MaxAge:  100,
			Options: []string{"not-valid"},
			wantErr: true,
		},
		{
			Name:    "BadOptions",
			MaxAge:  100,
			Options: []string{"includeSubDomains", "not-valid", "still-not-valid"},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		tt := tt
		t.Run(tt.Name, func(t *testing.T) {
			t.Parallel()

			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)
			})

			cfg, err := httpmw.HSTSConfigOptions(tt.MaxAge, tt.Options)
			if tt.wantErr {
				require.Error(t, err, "Expect error, HSTS(%v, %v)", tt.MaxAge, tt.Options)
				return
			}
			require.NoError(t, err, "Expect no error, HSTS(%v, %v)", tt.MaxAge, tt.Options)

			got := httpmw.HSTS(handler, cfg)
			req := httptest.NewRequest("GET", "/", nil)
			res := httptest.NewRecorder()
			got.ServeHTTP(res, req)

			require.Equal(t, tt.expectHeader, res.Header().Get("Strict-Transport-Security"), "expected header value")
		})
	}
}
