package chat

import (
	"fmt"
	"net/http"
	"strings"
	"time"

	"code.nonshy.com/nonshy/website/pkg/config"
	"code.nonshy.com/nonshy/website/pkg/models"
	"code.nonshy.com/nonshy/website/pkg/photo"
	"code.nonshy.com/nonshy/website/pkg/session"
	"code.nonshy.com/nonshy/website/pkg/templates"
	"github.com/golang-jwt/jwt/v4"
)

// JWT claims.
type Claims struct {
	// Custom claims.
	IsAdmin    bool   `json:"op"`
	Avatar     string `json:"img"`
	ProfileURL string `json:"url"`
	Nickname   string `json:"nick"`

	// Standard claims. Notes:
	// subject = username
	jwt.RegisteredClaims
}

// Landing page for chat rooms.
func Landing() http.HandlerFunc {
	tmpl := templates.Must("chat.html")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Get the current user.
		currentUser, err := session.CurrentUser(r)
		if err != nil {
			session.FlashError(w, r, "Couldn't get current user: %s", err)
			templates.Redirect(w, "/")
			return
		}

		// Are they logging into the chat room?
		var (
			intent = r.FormValue("intent")
			isShy  = currentUser.IsShy()
		)
		if intent == "join" {
			// If we are shy, block chat for now.
			if isShy {
				session.FlashError(w, r,
					"You have a Shy Account and are not allowed in the chat room at this time where our non-shy members may "+
						"be on camera.",
				)
				templates.Redirect(w, "/chat")
				return
			}

			// Get our Chat JWT secret.
			var (
				secret  = []byte(config.Current.BareRTC.JWTSecret)
				chatURL = config.Current.BareRTC.URL
			)
			if len(secret) == 0 || chatURL == "" {
				session.FlashError(w, r, "Couldn't sign you into the chat: JWT secret key or chat URL not configured!")
				templates.Redirect(w, r.URL.Path)
				return
			}

			// Avatar URL - masked if non-public.
			avatar := photo.URLPath(currentUser.ProfilePhoto.CroppedFilename)
			switch currentUser.ProfilePhoto.Visibility {
			case models.PhotoPrivate:
				avatar = "/static/img/shy-private.png"
			case models.PhotoFriends:
				avatar = "/static/img/shy-friends.png"
			}

			// Create the JWT claims.
			claims := Claims{
				IsAdmin:    currentUser.IsAdmin,
				Avatar:     avatar,
				ProfileURL: "/u/" + currentUser.Username,
				Nickname:   currentUser.NameOrUsername(),
				RegisteredClaims: jwt.RegisteredClaims{
					ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
					IssuedAt:  jwt.NewNumericDate(time.Now()),
					NotBefore: jwt.NewNumericDate(time.Now()),
					Issuer:    config.Title,
					Subject:   currentUser.Username,
					ID:        fmt.Sprintf("%d", currentUser.ID),
				},
			}
			token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
			ss, err := token.SignedString(secret)
			if err != nil {
				session.FlashError(w, r, "Couldn't sign you into the chat: %s", err)
				templates.Redirect(w, r.URL.Path)
				return
			}

			// Redirect them to the chat room.
			templates.Redirect(w, strings.TrimSuffix(chatURL, "/")+"/?jwt="+ss)
			return
		}

		var vars = map[string]interface{}{
			"ChatAPI":   strings.TrimSuffix(config.Current.BareRTC.URL, "/") + "/api/statistics",
			"IsShyUser": isShy,
		}
		if err := tmpl.Execute(w, r, vars); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})
}
