package webui

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
)

// Flash mirrors one Flask flash() message: (message, category).
type Flash struct {
	Category string `json:"c"`
	Message  string `json:"m"`
}

const flashCookieName = "flash"

// setFlash mirrors flask.flash(): appends one message to the flash cookie so it
// survives the redirect that (almost) always follows a form POST in this app.
// No signing: these are cosmetic toast notifications, not a trust boundary.
func setFlash(w http.ResponseWriter, category, message string) {
	flashes := []Flash{{Category: category, Message: message}}
	encoded, _ := json.Marshal(flashes)
	http.SetCookie(w, &http.Cookie{
		Name:     flashCookieName,
		Value:    base64.URLEncoding.EncodeToString(encoded),
		Path:     "/",
		HttpOnly: true,
		SameSite: http.SameSiteLaxMode,
	})
}

// popFlashes mirrors get_flashed_messages(with_categories=true): reads and clears the
// flash cookie so each message is shown exactly once, on the very next render.
func popFlashes(w http.ResponseWriter, r *http.Request) []Flash {
	c, err := r.Cookie(flashCookieName)
	if err != nil || c.Value == "" {
		return nil
	}
	http.SetCookie(w, &http.Cookie{Name: flashCookieName, Value: "", Path: "/", MaxAge: -1})
	raw, err := base64.URLEncoding.DecodeString(c.Value)
	if err != nil {
		return nil
	}
	var flashes []Flash
	if err := json.Unmarshal(raw, &flashes); err != nil {
		return nil
	}
	return flashes
}

// AppPasswordReveal carries a freshly-generated app password secret across the
// create->redirect hop, kept out of the toast-driven Flash system so it can render
// as its own centered modal (with a copy button) instead of a toast that's easy to
// miss and can't be copied without retyping.
type AppPasswordReveal struct {
	Label  string `json:"l"`
	Secret string `json:"s"`
}

const appPasswordRevealCookieName = "app_pw_reveal"

// setAppPasswordReveal mirrors setFlash but for the one-time secret reveal.
func setAppPasswordReveal(w http.ResponseWriter, label, secret string) {
	encoded, _ := json.Marshal(AppPasswordReveal{Label: label, Secret: secret})
	http.SetCookie(w, &http.Cookie{
		Name:     appPasswordRevealCookieName,
		Value:    base64.URLEncoding.EncodeToString(encoded),
		Path:     "/",
		HttpOnly: true,
		SameSite: http.SameSiteLaxMode,
	})
}

// popAppPasswordReveal mirrors popFlashes but for the one-time secret reveal.
func popAppPasswordReveal(w http.ResponseWriter, r *http.Request) *AppPasswordReveal {
	c, err := r.Cookie(appPasswordRevealCookieName)
	if err != nil || c.Value == "" {
		return nil
	}
	http.SetCookie(w, &http.Cookie{Name: appPasswordRevealCookieName, Value: "", Path: "/", MaxAge: -1})
	raw, err := base64.URLEncoding.DecodeString(c.Value)
	if err != nil {
		return nil
	}
	var reveal AppPasswordReveal
	if err := json.Unmarshal(raw, &reveal); err != nil {
		return nil
	}
	return &reveal
}
