package main

import (
	"fmt"
	"github.com/flamego/captcha"
	"github.com/flamego/flamego"
	"github.com/flamego/session"
	"github.com/flamego/template"
	"github.com/rs/zerolog/log"
	"golang.org/x/crypto/bcrypt"
	"image"
	user2 "kuvia/pkg/user"
	"net/http"
	"regexp"
	"time"
)

type User struct {
	Id int
	Username string
	Password string
	Name *string
	AboutMe *string `db:"aboutme"`
	Location *string
	Webpage *string
	Image *string
}

func loginForm(t template.Template, data template.Data, s session.Session, captcha captcha.Captcha, c flamego.Context) {
	fmt.Println(s.Get("user_id"))
	if s.Get("user_id") != nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}
	data["CaptchaHTML"] = captcha.HTML()
	t.HTML(http.StatusOK, "login")
}

func registerForm(t template.Template, data template.Data, s session.Session, captcha captcha.Captcha, c flamego.Context) {
	if s.Get("user_id") != nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}
	data["CaptchaHTML"] = captcha.HTML()
	t.HTML(http.StatusOK, "register")
}

func register(t template.Template, data template.Data, s session.Session, captcha captcha.Captcha, c flamego.Context) {
	if s.Get("user_id") != nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}
	username := c.Request().FormValue("username")
	password := c.Request().FormValue("password")
	//validate username
	var re = regexp.MustCompile(`^[a-z0-9]{8,25}$`)

	if re.Match([]byte(username)) == false {
		data["msg"] = "Username just contains lower letters and numbers"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "register")
		return
	}

	if len(password) < 8 {
		data["msg"] = "Password too short"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "register")
		return
	}

	//ca := c.Param("captcha")
	if captcha.ValidText(c.Request().FormValue("captcha")) == false {
		data["msg"] = "Please enter valide captcha code"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "register")
		return
	}

	//Check username exists
	usernameIsFree, err := user2.CheckUsernameIsFree(sqlConnection, username)
	if err != nil || usernameIsFree == false {
		data["msg"] = "Username is taken, choose another one"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "register")
		return
	}

	id, err := user2.Register(sqlConnection, username, password)
	if err != nil {
		panic(err)
	}
	fmt.Println(id)


	c.ResponseWriter().Write([]byte("OK"))
}

func logout(s session.Session, c flamego.Context) {
	s.Flush()
	c.Redirect("/login", http.StatusTemporaryRedirect)
}

func login(t template.Template, data template.Data, s session.Session, captcha captcha.Captcha, c flamego.Context) {
	if s.Get("user_id") != nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}
	username := c.Request().FormValue("username")
	password := c.Request().FormValue("password")

	/*if captcha.ValidText(c.Request().FormValue("captcha")) == false {
		data["msg"] = "Please enter valide captcha code"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "login")
		return
	}*/

	user, err := user2.GetUserByUsername(sqlConnection, username)
	if err != nil {
		data["msg"] = err.Error()
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "login")
		return
	}


	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		data["msg"] = "Wrong Password"
		data["CaptchaHTML"] = captcha.HTML()
		t.HTML(http.StatusOK, "login")
		return
	}

	s.Set("user_id", user.Id)

	c.Redirect("/", http.StatusTemporaryRedirect)
}

func profile(t template.Template, data template.Data, s session.Session, c flamego.Context) {
	if s.Get("user_id") == nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}

	user, err := user2.GetUserById(sqlConnection, s.Get("user_id").(int))
	if err != nil {
		panic(err)
	}
	data["user"] = user

	t.HTML(http.StatusOK, "settings_profile")
}

func profileUpdate(s session.Session, c flamego.Context)  {
	user, err := user2.GetUserById(sqlConnection, s.Get("user_id").(int))
	if err != nil {
		panic(err)
	}

	user.Name = c.Request().FormValue("name")
	user.AboutMe = c.Request().FormValue("aboutme")
	user.Location = c.Request().FormValue("location")
	user.Webpage = c.Request().FormValue("webpage")


	err = user2.UpdateUser(sqlConnection, user)
	if err != nil{
		panic(err)
	}
}

func profileImage(t template.Template, data template.Data, s session.Session, c flamego.Context) {
	if s.Get("user_id") == nil {
		c.Redirect("/", http.StatusTemporaryRedirect)
		return
	}

	user, err := user2.GetUserById(sqlConnection, s.Get("user_id").(int))
	if err != nil {
		panic(err)
	}
	data["user"] = user

	t.HTML(http.StatusOK, "settings_image")
}

func profileImageChange(s session.Session, c flamego.Context) {
	log.Debug().Msg("Change Profile Image")
	c.Request().ParseMultipartForm(9001)

	user, err := user2.GetUserById(sqlConnection, s.Get("user_id").(int))
	if err != nil {
		panic(err)
	}

	//Upload Croped Image
	file, _, err  := c.Request().FormFile("cropImage")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	cropedImage, _ , err := image.Decode(file)
	if err != nil {
		panic(err)
	}
	path := fmt.Sprintf("/user/%v/profilepic/%v-%v", user.Id, time.Now().UnixNano(), "crop.png")
	uploadImageToS3(cropedImage, path)

	//Upload Original Image

	fileOrginal, fileHeaderOrginal, err  := c.Request().FormFile("orginal")
	if err != nil {
		panic(err)
	}
	defer fileOrginal.Close()

	orignalImage, _ , err := image.Decode(fileOrginal)
	if err != nil {
		panic(err)
	}
	pathOrignal := fmt.Sprintf("/user/%v/profilepic/%v-orginal-%v", user.Id, time.Now().UnixNano(), fileHeaderOrginal.Filename)
	uploadImageToS3(orignalImage, pathOrignal)

	user.Image = path
	err = user2.UpdateUser(sqlConnection, user)
	if err != nil {
		panic(err)
	}
}