package controllers

import (
	"net/http"

	"git.kirsle.net/apps/gophertype/pkg/authentication"
	"git.kirsle.net/apps/gophertype/pkg/console"
	"git.kirsle.net/apps/gophertype/pkg/constants"
	"git.kirsle.net/apps/gophertype/pkg/models"
	"git.kirsle.net/apps/gophertype/pkg/ratelimit"
	"git.kirsle.net/apps/gophertype/pkg/responses"
	"git.kirsle.net/apps/gophertype/pkg/session"
	"github.com/albrow/forms"
)

func Login(w http.ResponseWriter, r *http.Request) {
	// Template variables.
	v := responses.NewTemplateVars(w, r)

	// POST handler: create the admin account.
	for r.Method == http.MethodPost {
		form, _ := forms.Parse(r)
		v.FormValues = form.Values

		// Validate form parameters.
		val := form.Validator()
		val.Require("email")
		val.MatchEmail("email")
		val.Require("password")
		if val.HasErrors() {
			v.ValidationError = val.ErrorMap()
			break
		}

		// Rate limit failed login attempts.
		limiter := &ratelimit.Limiter{
			Namespace:  "login",
			ID:         form.Get("email"),
			Limit:      constants.LoginRateLimit,
			Window:     constants.LoginRateLimitWindow,
			CooldownAt: constants.LoginRateLimitCooldownAt,
			Cooldown:   constants.LoginRateLimitCooldown,
		}

		// Check authentication.
		user, err := models.Users.AuthenticateUser(form.Get("email"), form.Get("password"))
		if err != nil {
			if err := limiter.Ping(); err != nil {
				v.Error = err
				break
			}
			v.Error = err
			break
		}

		if err := limiter.Clear(); err != nil {
			console.Error("Failed to clear the login rate limiter: %s", err)
		}

		_ = user

		authentication.Login(w, r, user)
		session.Flash(w, r, "Signed in!")
		responses.Redirect(w, r, "/") // TODO: next URL
		return
	}

	responses.RenderTemplate(w, r, "_builtin/users/login.gohtml", v)
}

func Logout(w http.ResponseWriter, r *http.Request) {
	authentication.Logout(w, r)
	session.Flash(w, r, "Signed out!")
	responses.Redirect(w, r, "/")
}
