package web

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"net/http"
	"time"

	"party.at/party/cmd/party/common"
	"party.at/party/internal/data"
)

func (web *Web) Home(w http.ResponseWriter, r *http.Request) {
	if !common.GetUser(r).IsAnonymous() {
		http.Redirect(w, r, "/issues", http.StatusSeeOther)
		return
	}
	web.render(w, r, http.StatusOK, "home_anonymous", struct {
		AuthenticatedUser *data.User
		FormErrors        []string
		IsDevelopment     bool
	}{
		IsDevelopment: web.App.Config.Env == "development",
	})
}

func (web *Web) Login(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	token, err := web.App.LoginUser(r.PostFormValue("email"), r.PostFormValue("password"))
	if err != nil {
		var msg string
		if errors.Is(err, data.ErrInvalidCredentials) {
			msg = "Ungültige E-Mail-Adresse oder Passwort."
		} else {
			web.App.LogError(r, err)
			msg = "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut."
		}
		web.render(w, r, http.StatusUnprocessableEntity, "home_anonymous", struct {
			AuthenticatedUser *data.User
			FormErrors        []string
			IsDevelopment     bool
		}{
			FormErrors:    []string{msg},
			IsDevelopment: web.App.Config.Env == "development",
		})
		return
	}

	setCookie(w, token.Plaintext, token.Expiry)
	http.Redirect(w, r, "/issues", http.StatusSeeOther)
}

func (web *Web) DevLogin(w http.ResponseWriter, r *http.Request) {
	if web.App.Config.Env != "development" {
		http.NotFound(w, r)
		return
	}

	b := make([]byte, 8)
	if _, err := rand.Read(b); err != nil {
		web.App.LogError(r, err)
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	suffix := hex.EncodeToString(b)

	_, authToken, err := web.App.RegisterUser(common.RegisterUserInput{
		ProviderID:  1,
		Username:    fmt.Sprintf("dev-%s", suffix),
		Email:       fmt.Sprintf("dev-%s@test.local", suffix),
		Password:    "devpassword123",
		Name:        fmt.Sprintf("Dev User %s", suffix),
		DateOfBirth: time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC),
		Country:     "AT",
		PhoneNumber: "+43000000000",
		Address:     "Teststraße 1, 1010 Wien",
	})
	if err != nil {
		web.App.LogError(r, err)
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	setCookie(w, authToken.Plaintext, authToken.Expiry)
	http.Redirect(w, r, "/issues", http.StatusSeeOther)
}

func (web *Web) Logout(w http.ResponseWriter, r *http.Request) {
	if cookie, err := r.Cookie(cookieName); err == nil {
		_ = web.App.DeleteToken(cookie.Value)
	}
	clearCookie(w)
	http.Redirect(w, r, "/", http.StatusSeeOther)
}
