package frontend

import (
	"fmt"
	"html/template"
	"log"
	"net/http"

	b "streifling.com/jason/cpolis/cmd/backend"
)

func saveSession(w http.ResponseWriter, r *http.Request, s *b.CookieStore, u *b.User) error {
	session, err := s.Get(r, "cookie")
	if err != nil {
		return fmt.Errorf("error getting session: %v", err)
	}

	session.Values["authenticated"] = true
	session.Values["id"] = u.ID
	session.Values["name"] = u.FirstName + u.LastName
	session.Values["role"] = u.Role
	if err := session.Save(r, w); err != nil {
		return fmt.Errorf("error saving session: %v", err)
	}

	return nil
}

func HomePage(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		numRows, err := db.CountEntries("users")
		if err != nil {
			log.Fatalln(err)
		}

		files := []string{c.WebDir + "/templates/index.html"}
		if numRows == 0 {
			files = append(files, c.WebDir+"/templates/first-user.html")
			tmpl, err := template.ParseFiles(files...)
			template.Must(tmpl, err).Execute(w, nil)
		} else {
			session, _ := s.Get(r, "cookie")
			if auth, ok := session.Values["authenticated"].(bool); auth && ok {
				files = append(files, c.WebDir+"/templates/hub.html")
				tmpl, err := template.ParseFiles(files...)
				template.Must(tmpl, err).Execute(w, session.Values["role"])
			} else {
				files = append(files, c.WebDir+"/templates/login.html")
				tmpl, err := template.ParseFiles(files...)
				template.Must(tmpl, err).Execute(w, nil)
			}
		}
	}
}

func Login(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		userName := r.PostFormValue("username")
		password := r.PostFormValue("password")

		id, ok := db.GetID(userName)
		if !ok {
			http.Error(w, fmt.Sprintf("no such user: %v", userName), http.StatusBadRequest)
			return
		}

		if err := db.CheckPassword(id, password); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		user, err := db.GetUser(id)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if err := saveSession(w, r, s, user); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
		template.Must(tmpl, err).ExecuteTemplate(w, "page-content", user.Role)
	}
}

func Logout(c *b.Config, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		session, err := getSession(w, r, c, s)
		if err != nil {
			return
		}

		session.Options.MaxAge = -1
		if err = session.Save(r, w); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html")
		template.Must(tmpl, err).ExecuteTemplate(w, "page-content", nil)
	}
}

func ShowHub(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		session, err := getSession(w, r, c, s)
		if err != nil {
			return
		}

		session.Values["article"] = nil
		if err = session.Save(r, w); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
		template.Must(tmpl, err).ExecuteTemplate(w, "page-content", session.Values["role"].(int))
	}
}