package router

import (
	"context"
	"log/slog"
	"net/http"
	"slices"
	"strings"

	"github.com/SecurityBrewery/catalyst/app/database"
	"github.com/SecurityBrewery/catalyst/app/database/sqlc"
)

func demoMode(queries *sqlc.Queries) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if isCriticalPath(r) && isCriticalMethod(r) && isDemoMode(r.Context(), queries) {
				http.Error(w, "Cannot modify reactions or files in demo mode", http.StatusForbidden)

				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

func isCriticalPath(r *http.Request) bool {
	// Define critical paths that should not be accessed in demo mode
	criticalPaths := []string{
		"/api/files",
		"/api/groups",
		"/api/reactions",
		"/api/settings",
		"/api/users",
		"/api/webhooks",
	}

	for _, path := range criticalPaths {
		if strings.Contains(r.URL.Path, path) {
			return true
		}
	}

	return false
}

func isCriticalMethod(r *http.Request) bool {
	return !slices.Contains([]string{http.MethodHead, http.MethodGet}, r.Method)
}

func isDemoMode(ctx context.Context, queries *sqlc.Queries) bool {
	var demoMode bool

	if err := database.Paginate(ctx, func(ctx context.Context, offset, limit int64) (nextPage bool, err error) {
		slog.InfoContext(ctx, "Checking for demo mode", "offset", offset, "limit", limit)

		features, err := queries.ListFeatures(ctx, sqlc.ListFeaturesParams{Offset: offset, Limit: limit})
		if err != nil {
			return false, err
		}

		for _, feature := range features {
			if feature.Key == "demo" {
				demoMode = true

				return false, nil // Stop pagination if demo mode is found
			}
		}

		return len(features) > 0, nil
	}); err != nil {
		slog.ErrorContext(ctx, "Failed to check demo mode", "error", err)

		return false
	}

	return demoMode
}
