package handlers

import (
	"fmt"
	"net/http"

	"git.haelnorr.com/h/golib/hws"
	"github.com/pkg/errors"
)

// throwError is a generic helper that all throw* functions use internally
func throwError(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	statusCode int,
	msg string,
	err error,
	level string,
) {
	err = s.ThrowError(w, r, hws.HWSError{
		StatusCode:      statusCode,
		Message:         msg,
		Error:           err,
		Level:           hws.ErrorLevel(level),
		RenderErrorPage: true, // throw* family always renders error pages
	})
	if err != nil {
		s.ThrowFatal(w, err)
	}
}

// throwInternalServiceError handles 500 errors (server failures)
func throwInternalServiceError(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusInternalServerError, msg, err, "error")
}

// throwBadRequest handles 400 errors (malformed requests)
func throwBadRequest(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusBadRequest, msg, err, "debug")
}

// throwForbidden handles 403 errors (normal permission denials)
func throwForbidden(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusForbidden, msg, err, "debug")
}

// throwForbiddenSecurity handles 403 errors for security events (uses WARN level)
func throwForbiddenSecurity(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusForbidden, msg, err, "warn")
}

// throwUnauthorized handles 401 errors (not authenticated)
func throwUnauthorized(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusUnauthorized, msg, err, "debug")
}

// throwUnauthorizedSecurity handles 401 errors for security events (uses WARN level)
func throwUnauthorizedSecurity(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	msg string,
	err error,
) {
	throwError(s, w, r, http.StatusUnauthorized, msg, err, "warn")
}

// throwNotFound handles 404 errors
func throwNotFound(
	s *hws.Server,
	w http.ResponseWriter,
	r *http.Request,
	path string,
) {
	msg := fmt.Sprintf("The requested resource was not found: %s", path)
	err := errors.New("Resource not found")
	throwError(s, w, r, http.StatusNotFound, msg, err, "debug")
}
