package auth

import (
	"net/http"

	"git.faercol.me/faercol/polyculeconnect/polyculeconnect/helpers"
	"git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/storage"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

const AuthCallbackRoute = "/callback"

type AuthCallbackController struct {
	l  *zap.SugaredLogger
	st *storage.Storage
}

func NewAuthCallbackController(l *zap.SugaredLogger, st *storage.Storage) *AuthCallbackController {
	return &AuthCallbackController{
		l:  l,
		st: st,
	}
}

func (c *AuthCallbackController) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	errMsg := r.URL.Query().Get("error")
	if errMsg != "" {
		errorDesc := r.URL.Query().Get("error_description")
		c.l.Errorf("Failed to perform authentication: %s (%s)", errMsg, errorDesc)
		helpers.HandleResponse(w, r, http.StatusInternalServerError, []byte("failed to perform authentication"), c.l)
		return
	}

	code := r.URL.Query().Get("code")
	state := r.URL.Query().Get("state")
	if code == "" || state == "" {
		c.l.Error("Missing code or state in response")
		helpers.HandleResponse(w, r, http.StatusInternalServerError, []byte("failed to perform authentication"), c.l)
		return
	}

	requestID, err := uuid.Parse(state)
	if err != nil {
		c.l.Errorf("Invalid state, should be a request UUID, but got %s: %s", state, err)
		helpers.HandleResponse(w, r, http.StatusInternalServerError, []byte("failed to perform authentication"), c.l)
		return
	}

	err = c.st.LocalStorage.AuthRequestStorage().ValidateAuthRequest(r.Context(), requestID)
	if err != nil {
		c.l.Errorf("Failed to validate auth request from storage: %s", err)
		helpers.HandleResponse(w, r, http.StatusInternalServerError, []byte("failed to perform authentication"), c.l)
		return
	}

	http.Redirect(w, r, "/authorize/callback?id="+state, http.StatusFound)
}
