package hub

import (
	"log"
	"net/http"
	"vppn/hub/api"

	"git.crumpington.com/lib/go/webutil"
)

type handlerFunc func(s *api.Session, w http.ResponseWriter, r *http.Request) error

func (app *App) handlePub(pattern string, fn handlerFunc) {
	wrapped := func(w http.ResponseWriter, r *http.Request) {
		sessionID := app.getCookie(r, SESSION_ID_COOKIE_NAME)
		s, err := app.api.Session_Get(sessionID)
		if err != nil {
			log.Printf("Failed to get session: %v", err)
			http.Error(w, "Internal error", http.StatusInternalServerError)
			return
		}

		if s.SessionID != sessionID {
			app.setCookie(w, SESSION_ID_COOKIE_NAME, s.SessionID)
		}

		if r.Method == http.MethodPost {
			r.ParseMultipartForm(64 * 1024)
			if r.FormValue("CSRF") != s.CSRF {
				log.Printf("%s != %s", r.FormValue("CSRF"), s.CSRF)
				http.Error(w, "CSRF mismatch", http.StatusBadRequest)
				return
			}
		} else {
			r.ParseForm()
		}

		if err := fn(s, w, r); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}

	app.mux.HandleFunc(pattern,
		webutil.WithLogging(
			wrapped))
}

func (app *App) handleNotSignedIn(pattern string, fn handlerFunc) {
	app.handlePub(pattern, func(s *api.Session, w http.ResponseWriter, r *http.Request) error {
		if s.SignedIn {
			http.Redirect(w, r, "/", http.StatusSeeOther)
			return nil
		}
		return fn(s, w, r)
	})
}

func (app *App) handleSignedIn(pattern string, fn handlerFunc) {
	app.handlePub(pattern, func(s *api.Session, w http.ResponseWriter, r *http.Request) error {
		if !s.SignedIn {
			http.Redirect(w, r, "/", http.StatusSeeOther)
			return nil
		}
		return fn(s, w, r)
	})
}

type peerHandlerFunc func(p *api.Peer, w http.ResponseWriter, r *http.Request) error

func (app *App) handlePeer(pattern string, fn peerHandlerFunc) {
	wrapped := func(w http.ResponseWriter, r *http.Request) {
		_, apiKey, ok := r.BasicAuth()
		if !ok {
			http.Error(w, "Not authorized", http.StatusUnauthorized)
			return
		}

		peer, err := app.api.Peer_GetByAPIKey(apiKey)
		if err != nil {
			http.Error(w, "Not authorized", http.StatusUnauthorized)
			return
		}

		r.ParseForm()
		if err := fn(peer, w, r); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	app.mux.HandleFunc(pattern,
		webutil.WithLogging(
			wrapped))
}
