package httpapi

import (
	"net/http"
	"net/url"
	"strings"
)

type authConfigResp struct {
	AuthMode  string `json:"auth_mode"`
	BrokerURL string `json:"broker_url"`
	BrokerApp string `json:"broker_app"`
}

// handleAuthConfig publishes the Auth Broker coordinates native clients (the desktop)
// need to run the broker device-authorization flow: the broker's public URL + this
// app's key in the broker apps registry. Public (it bootstraps native login).
func (s *Server) handleAuthConfig(w http.ResponseWriter, _ *http.Request) {
	writeJSON(w, http.StatusOK, authConfigResp{
		AuthMode:  s.cfg.AuthMode,
		BrokerURL: s.cfg.BrokerPublicURL,
		BrokerApp: s.cfg.BrokerAppOrDefault(),
	})
}

// handleAuthLogin 302-redirects the browser to the Auth Broker's public login page
// for global SSO (the broker handles Casdoor and sets its domain cookie; on return the
// edge injects X-Auth from that cookie). cdrop owns this redirect so the broker's
// public URL lives in one server-side config. Public (it bootstraps login). The rd
// (return target) is constrained to this deployment's own origin — an open-redirect
// guard — defaulting to the site root.
func (s *Server) handleAuthLogin(w http.ResponseWriter, r *http.Request) {
	if s.cfg.BrokerPublicURL == "" {
		writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "login redirect not configured"})
		return
	}
	rd := s.safeReturnTarget(r.URL.Query().Get("rd"))
	dest := strings.TrimRight(s.cfg.BrokerPublicURL, "/") + "/login?rd=" + url.QueryEscape(rd)
	http.Redirect(w, r, dest, http.StatusFound)
}

// safeReturnTarget validates a post-login return URL against this deployment's origin,
// falling back to the site root. It blocks open redirects: only a same-origin absolute
// URL (or, when no site origin is configured in dev, a site-relative path) is accepted.
func (s *Server) safeReturnTarget(rd string) string {
	if s.siteOrigin == "" {
		// dev: accept only a site-relative path, never an absolute URL.
		if strings.HasPrefix(rd, "/") && !strings.HasPrefix(rd, "//") {
			return rd
		}
		return "/"
	}
	if u, err := url.Parse(rd); err == nil && u.Scheme != "" && u.Host != "" {
		if u.Scheme+"://"+u.Host == s.siteOrigin {
			return rd
		}
	}
	return s.siteOrigin + "/"
}
