package provision

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"
)

func authorizeProvision(r *http.Request, secret string) bool {
	if secret == "" {
		return false
	}
	if r.Header.Get("X-Provision-Secret") == secret {
		return true
	}
	if r.URL.Query().Get("secret") == secret {
		return true
	}
	return false
}

type authentikWebhookPayload struct {
	Email      string `json:"email"`
	Username   string `json:"username"`
	Name       string `json:"name"`
	Password   string `json:"password"`
	ExternalID string `json:"external_id"`
	Sub        string `json:"sub"`
	User       struct {
		Email    string `json:"email"`
		Username string `json:"username"`
		Name     string `json:"name"`
		UUID     string `json:"uuid"`
		PK       int    `json:"pk"`
	} `json:"user"`
}

func decodeProvisionBody(r *http.Request) (provisionUserRequest, error) {
	var ak authentikWebhookPayload
	if err := json.NewDecoder(r.Body).Decode(&ak); err != nil {
		return provisionUserRequest{}, err
	}

	req := provisionUserRequest{
		Email:      firstNonEmpty(ak.Email, ak.User.Email),
		Username:   firstNonEmpty(ak.Username, ak.User.Username),
		Name:       firstNonEmpty(ak.Name, ak.User.Name),
		Password:   ak.Password,
		ExternalID: firstNonEmpty(ak.ExternalID, ak.Sub, ak.User.UUID),
	}
	if req.ExternalID == "" && ak.User.PK > 0 {
		req.ExternalID = strconv.Itoa(ak.User.PK)
	}
	normalizeProvisionRequest(&req)
	return req, nil
}

func normalizeProvisionRequest(dst *provisionUserRequest) {
	if dst.Email == "" {
		dst.Email = strings.ToLower(strings.TrimSpace(dst.Username))
	}
	if dst.Name == "" {
		dst.Name = dst.Email
	}
}

func firstNonEmpty(values ...string) string {
	for _, v := range values {
		if strings.TrimSpace(v) != "" {
			return strings.TrimSpace(v)
		}
	}
	return ""
}
