package poll

import (
	"fmt"
	"net/http"
	"strconv"

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

// Vote controller for polls.
func Vote() http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var (
			// Form parameters
			pollID       uint64
			fromThreadID uint64
			answers      = r.Form["answer"] // a slice in case of MultipleChoice
			nextURL      string
		)

		// Parse integer params.
		if value, err := strconv.Atoi(r.FormValue("poll_id")); err != nil {
			session.FlashError(w, r, "Invalid poll ID")
			templates.Redirect(w, "/")
			return
		} else {
			pollID = uint64(value)
		}

		// Currently polls only exist in forum threads, require the thread ID.
		if value, err := strconv.Atoi(r.FormValue("from_thread_id")); err != nil {
			session.FlashError(w, r, "Invalid thread ID")
			templates.Redirect(w, "/")
			return
		} else {
			fromThreadID = uint64(value)
			nextURL = fmt.Sprintf("/forum/thread/%d", fromThreadID)
		}

		// POST request only.
		if r.Method != http.MethodPost {
			session.FlashError(w, r, "POST requests only.")
			templates.Redirect(w, nextURL)
			return
		}

		// An answer is required.
		if len(answers) == 0 || len(answers) == 1 && answers[0] == "" {
			session.FlashError(w, r, "An answer to this poll is required for voting.")
			templates.Redirect(w, nextURL)
			return
		}

		// Get the current user.
		user, err := session.CurrentUser(r)
		if err != nil {
			session.FlashError(w, r, "Unexpected error: couldn't get CurrentUser")
			templates.Redirect(w, nextURL)
			return
		}

		// Look up the poll.
		poll, err := models.GetPoll(pollID)
		if err != nil {
			session.FlashError(w, r, "Poll not found.")
			templates.Redirect(w, nextURL)
			return
		}

		// Is it accepting responses?
		result := poll.Result(user)
		if !result.AcceptingVotes {
			session.FlashError(w, r, "This poll is not accepting your vote at this time.")
			templates.Redirect(w, nextURL)
			return
		}

		// Cast the vote!
		if err := poll.CastVote(user, answers); err != nil {
			session.FlashError(w, r, "Couldn't cast the vote: %s", err)
			templates.Redirect(w, nextURL)
			return
		}

		session.Flash(w, r, "Your vote has been recorded!")
		templates.Redirect(w, nextURL)
	})
}
