package middleware

import (
	"net/http"

	"leadb2b.org/internal/auth"
)

func RequireAuth(authSvc *auth.Service) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			token := authSvc.TokenFromRequest(r)
			sess, err := authSvc.ResolveSession(r.Context(), token)
			if err != nil || sess == nil {
				if isAPI(r) {
					writeJSONError(w, http.StatusUnauthorized, "UNAUTHORIZED", "Faça login para continuar")
					return
				}
				http.Redirect(w, r, "/login?next="+r.URL.Path, http.StatusFound)
				return
			}
			ctx := auth.WithSession(r.Context(), sess)
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}

func RequireActivePlan(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		sess := auth.SessionFromContext(r.Context())
		limits := sess.Limits()
		if sess == nil || limits == nil || sess.Me.Product == nil || !sess.Me.Product.Access.CanUseApp {
			if isAPI(r) {
				writeJSONError(w, http.StatusForbidden, "PLAN_INACTIVE", "Plano inativo ou expirado")
				return
			}
			http.Error(w, "Plano inativo. Acesse /app/plano para mais informações.", http.StatusForbidden)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func RequireAdmin(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		sess := auth.SessionFromContext(r.Context())
		if sess == nil || !sess.IsAdmin() {
			if isAPI(r) {
				writeJSONError(w, http.StatusForbidden, "FORBIDDEN", "Acesso restrito a administradores")
				return
			}
			http.Error(w, "Acesso negado", http.StatusForbidden)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func isAPI(r *http.Request) bool {
	return len(r.URL.Path) >= 8 && r.URL.Path[:8] == "/api/v1/"
}

func writeJSONError(w http.ResponseWriter, status int, code, message string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_, _ = w.Write([]byte(`{"error":{"code":"` + code + `","message":"` + message + `"}}`))
}
