package auth

import (
	"context"
	"net/http"

	"logjensticks/internal/db"
)

const CookieName = "session_token"

type contextKey string

const sessionContextKey contextKey = "session"

// Middleware validates the session cookie on every request. Attach this to
// any route that requires authentication.
func Middleware(dbc *db.Client) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			cookie, err := r.Cookie(CookieName)
			if err != nil {
				writeUnauthorized(w)
				return
			}

			session, err := ValidateSession(r.Context(), dbc, cookie.Value)
			if err != nil {
				writeUnauthorized(w)
				return
			}

			ctx := context.WithValue(r.Context(), sessionContextKey, session)
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}

// SessionFromContext retrieves the validated session attached by Middleware.
// Returns nil if called outside an authenticated route.
func SessionFromContext(ctx context.Context) *Session {
	s, _ := ctx.Value(sessionContextKey).(*Session)
	return s
}

func writeUnauthorized(w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusUnauthorized)
	w.Write([]byte(`{"success":false,"data":null,"error":{"code":"UNAUTHORIZED","message":"authentication required"}}`))
}
