package forum

import (
	"net/http"
	"strconv"
	"strings"

	"code.nonshy.com/nonshy/website/pkg/config"
	"code.nonshy.com/nonshy/website/pkg/models"
	"code.nonshy.com/nonshy/website/pkg/session"
	"code.nonshy.com/nonshy/website/pkg/templates"
)

// AddEdit page.
func AddEdit() http.HandlerFunc {
	tmpl := templates.Must("forum/add_edit.html")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Are we editing a forum or creating a new one?
		var editID uint64
		if editStr := r.FormValue("id"); editStr != "" {
			if i, err := strconv.Atoi(editStr); err == nil {
				editID = uint64(i)
			} else {
				session.FlashError(w, r, "Edit parameter: id was not an integer")
				templates.Redirect(w, "/forum/admin")
				return
			}
		}

		// 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
		}

		// If editing, look up the existing forum.
		var forum *models.Forum
		if editID > 0 {
			if found, err := models.GetForum(editID); err != nil {
				session.FlashError(w, r, "Couldn't get forum: %s", err)
				templates.Redirect(w, "/forum/admin")
				return
			} else {
				// Do we have permission?
				if found.OwnerID != currentUser.ID && !currentUser.IsAdmin {
					templates.ForbiddenPage(w, r)
					return
				}

				forum = found
			}
		}

		// Saving?
		if r.Method == http.MethodPost {
			var (
				title          = strings.TrimSpace(r.PostFormValue("title"))
				fragment       = strings.TrimSpace(strings.ToLower(r.PostFormValue("fragment")))
				description    = strings.TrimSpace(r.PostFormValue("description"))
				category       = strings.TrimSpace(r.PostFormValue("category"))
				isExplicit     = r.PostFormValue("explicit") == "true"
				isPrivileged   = r.PostFormValue("privileged") == "true"
				isPermitPhotos = r.PostFormValue("permit_photos") == "true"
				isInnerCircle  = r.PostFormValue("inner_circle") == "true"
			)

			// Sanity check admin-only settings.
			if !currentUser.IsAdmin {
				isPrivileged = false
				isPermitPhotos = false
			}

			// Were we editing an existing forum?
			if forum != nil {
				forum.Title = title
				forum.Description = description
				forum.Category = category
				forum.Explicit = isExplicit
				forum.Privileged = isPrivileged
				forum.PermitPhotos = isPermitPhotos
				forum.InnerCircle = isInnerCircle

				// Save it.
				if err := forum.Save(); err == nil {
					session.Flash(w, r, "Forum has been updated!")
					templates.Redirect(w, "/forum/admin")
					return
				} else {
					session.FlashError(w, r, "Error saving the forum: %s", err)
				}
			} else {
				// Validate the fragment. Front-end enforces the pattern so this
				// is just a sanity check.
				if m := FragmentRegexp.FindStringSubmatch(fragment); m == nil {
					session.FlashError(w, r, "The fragment format is invalid.")
					templates.Redirect(w, "/forum/admin")
					return
				}

				// Ensure the fragment is unique.
				if _, err := models.ForumByFragment(fragment); err == nil {
					session.FlashError(w, r, "The forum fragment is already in use.")
				} else {
					// Create the forum.
					forum = &models.Forum{
						Owner:        *currentUser,
						Category:     category,
						Fragment:     fragment,
						Title:        title,
						Description:  description,
						Explicit:     isExplicit,
						Privileged:   isPrivileged,
						PermitPhotos: isPermitPhotos,
						InnerCircle:  isInnerCircle,
					}

					if err := models.CreateForum(forum); err == nil {
						session.Flash(w, r, "The forum has been created!")
						templates.Redirect(w, "/forum/admin")
						return
					} else {
						session.FlashError(w, r, "Error creating the forum: %s", err)
					}
				}
			}
		}

		_ = editID

		var vars = map[string]interface{}{
			"EditID":     editID,
			"EditForum":  forum,
			"Categories": config.ForumCategories,
		}
		if err := tmpl.Execute(w, r, vars); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})
}
