package oauth

import (
	"fmt"
	"net/http"
	"slices"
	"strings"

	"gitea.local/admin/hspguard/internal/web"
)

// client_id=gitea-client&redirect_uri=https://git.adalspace.com/user/oauth2/Home%20Guard/callback&response_type=code&scope=openid&state=4c3b4a25-9cf9-4b18-afc0-270e1078eb40
func (h *OAuthHandler) AuthorizeClient(w http.ResponseWriter, r *http.Request) {
	redirectUri := r.URL.Query().Get("redirect_uri")
	if redirectUri == "" {
		web.Error(w, "redirect_uri is missing in request", http.StatusBadRequest)
		return
	}

	state := r.URL.Query().Get("state")

	clientId := r.URL.Query().Get("client_id")
	if clientId == "" {
		uri := fmt.Sprintf("%s?error=invalid_request&error_description=ClientID+is+missing", redirectUri)
		if state != "" {
			uri += "&state=" + state
		}
		http.Redirect(w, r, uri, http.StatusFound)
		return
	}

	client, err := h.repo.GetApiServiceCID(r.Context(), clientId)
	if err != nil {
		uri := fmt.Sprintf("%s?error=access_denied&error_description=Service+not+authorized", redirectUri)
		if state != "" {
			uri += "&state=" + state
		}
		http.Redirect(w, r, uri, http.StatusFound)
		return
	}

	if !client.IsActive {
		uri := fmt.Sprintf("%s?error=temporarily_unavailable&error_description=Service+not+active", redirectUri)
		if state != "" {
			uri += "&state=" + state
		}
		http.Redirect(w, r, uri, http.StatusFound)
		return
	}

	scopes := strings.SplitSeq(strings.TrimSpace(r.URL.Query().Get("scope")), " ")

	for scope := range scopes {
		if !slices.Contains(client.Scopes, scope) {
			uri := fmt.Sprintf("%s?error=invalid_scope&error_description=Scope+%s+is+not+allowed", redirectUri, strings.ReplaceAll(scope, " ", "+"))
			if state != "" {
				uri += "&state=" + state
			}
			http.Redirect(w, r, uri, http.StatusFound)
			return
		}
	}

	if !slices.Contains(client.RedirectUris, redirectUri) {
		uri := fmt.Sprintf("%s?error=invalid_request&error_description=Redirect+URI+is+not+allowed", redirectUri)
		if state != "" {
			uri += "&state=" + state
		}
		http.Redirect(w, r, uri, http.StatusFound)
		return
	}

	http.Redirect(w, r, fmt.Sprintf("/auth?%s", r.URL.Query().Encode()), http.StatusFound)
}
