package contact

import (
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/gorilla/mux"
	"github.com/kirsle/blog/src/forms"
	"github.com/kirsle/blog/src/log"
	"github.com/kirsle/blog/src/mail"
	"github.com/kirsle/blog/src/markdown"
	"github.com/kirsle/blog/src/render"
	"github.com/kirsle/blog/src/responses"
	"github.com/kirsle/blog/models/settings"
)

// Register attaches the contact URL to the app.
func Register(r *mux.Router) {
	r.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) {
		// Allow ?next= to redirect to other local pages.
		nextURL := r.FormValue("next")
		if nextURL != "" && nextURL[0] != '/' {
			log.Error("/contact?next=: URL must be a local page beginning with /")
			nextURL = ""
		}

		form := &forms.Contact{}
		v := map[string]interface{}{
			"Form": form,
		}

		// If there is no site admin, show an error.
		cfg, err := settings.Load()
		if err != nil {
			responses.Error(w, r, "Error loading site configuration!")
			return
		} else if cfg.Site.AdminEmail == "" {
			responses.Error(w, r, "There is no admin email configured for this website!")
			return
		} else if !cfg.Mail.Enabled {
			responses.Error(w, r, "This website doesn't have an e-mail gateway configured.")
			return
		}

		// Posting?
		if r.Method == http.MethodPost {
			form.ParseForm(r)
			if err = form.Validate(); err != nil {
				// If they're not from the /contact front-end, redirect them
				// with the flash.
				if len(nextURL) > 0 {
					responses.FlashAndRedirect(w, r, nextURL, err.Error())
					return
				}

				// Otherwise flash and let the /contact page render to retain
				// their form fields so far.
				responses.Flash(w, r, err.Error())
			} else {
				go mail.SendEmail(mail.Email{
					To:       cfg.Site.AdminEmail,
					Admin:    true,
					ReplyTo:  form.Email,
					Subject:  fmt.Sprintf("Contact Form on %s: %s", cfg.Site.Title, form.Subject),
					Template: ".email/contact.gohtml",
					Data: map[string]interface{}{
						"Name":    form.Name,
						"Message": template.HTML(markdown.RenderMarkdown(form.Message)),
						"Email":   form.Email,
					},
				})

				// Log it to disk, too.
				fh, err := os.OpenFile(filepath.Join(*render.UserRoot, ".contact.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
				if err != nil {
					responses.Flash(w, r, "Error logging the message to disk: %s", err)
				} else {
					fh.WriteString(fmt.Sprintf(
						"Date: %s\nName: %s\nEmail: %s\nSubject: %s\n\n%s\n\n--------------------\n\n",
						time.Now().Format(time.UnixDate),
						form.Name,
						form.Email,
						form.Subject,
						form.Message,
					))
					fh.Close()
				}

				if len(nextURL) > 0 {
					responses.FlashAndRedirect(w, r, nextURL, "Your message has been sent.")
				} else {
					responses.FlashAndRedirect(w, r, "/contact", "Your message has been sent.")
				}
				return
			}
		}

		render.Template(w, r, "contact", v)
	})
}
