package public_handlers

import (
	"cpone/models"
	"cpone/utils"
	public_login "cpone/views/public/login"
	"encoding/json"
	"net/http"
	"time"

	"github.com/golang-jwt/jwt/v5"
	"github.com/labstack/echo/v4"
	"go.uber.org/zap"
)

type LoginService interface {
	MultiSignIn(username string, password string, host string) (models.Response, error)
}

func NewLoginHandler(us LoginService) *LoginHandler {
	return &LoginHandler{
		LoginService: us,
	}
}

type LoginHandler struct {
	LoginService LoginService
}

func (lh *LoginHandler) HandlerShowLogin(c echo.Context) error {

	si := public_login.ShowLogin("Login ", public_login.MainLogin(true), public_login.CssLogin(), public_login.JsLogin())

	return utils.View(c, si)
}

func (lh *LoginHandler) HandleSignIn(c echo.Context) error {
	logger, _ := zap.NewProduction()
	host := c.Request().Host
	username := c.FormValue("username")
	password := c.FormValue("password")
	defer logger.Sync()
	logger.Info("Params", zap.Any("username", username), zap.Any("pass", password))

	resp, err := lh.LoginService.MultiSignIn(username, password, host)
	if err != nil {
		defer logger.Sync()
		logger.Info("Error", zap.Any("error multi signin", err))

		si := public_login.ShowLogin("Login", public_login.MainLogin(false), public_login.CssLogin(), public_login.JsLogin())
		return utils.View(c, si)
	}
	if resp.Status == "ERR" {
		defer logger.Sync()
		logger.Info("Error", zap.Any("ERR", resp.Status))

		si := public_login.ShowLogin("Login", public_login.MainLogin(false), public_login.CssLogin(), public_login.JsLogin())
		return utils.View(c, si)
	}

	defer logger.Sync()
	logger.Info("valid", zap.Any("value", resp))

	var url string
	switch resp.Data.Type {
	case "cpone":
		url = "/one-ui"
	case "pic":
		url = "/corp/dashboard_pic"
	case "patient":
		url = "/corp/dashboard_pat"
	default:
		url = "/one-ui"
	}

	user, err := json.Marshal(resp.Data.User)
	if err != nil {
		defer logger.Sync()
		logger.Info("Error", zap.Error(err))

		si := public_login.ShowLogin("Login ", public_login.MainLogin(false), public_login.CssLogin(), public_login.JsLogin())
		return utils.View(c, si)
	}

	cookie := new(http.Cookie)
	cookie.Name = "token"
	cookie.Value = resp.Data.Token
	cookie.Path = "/"
	cookie.HttpOnly = true

	c.SetCookie(cookie)

	userString := string(user)
	store := `
	<script>
		console.log("store token");
		const token = "` + resp.Data.Token + `";
		const user = JSON.stringify(` + userString + `);
		localStorage.setItem("token", token);
		localStorage.setItem("user", user);

		htmx.on("htmx:configRequest", (e)=> {
			e.detail.headers["Authorization"] = "Bearer ` + resp.Data.Token + `"
		})		

		setTimeout(() => {
			htmx.ajax('GET', '/login/redirect?url=` + url + `')
		}, 200)
	</script>	
	`
	c.Response().Header().Set("HX-Trigger", "script")
	return c.String(http.StatusOK, store)
}

func (lh *LoginHandler) HandleRedirect(c echo.Context) error {
	logger, _ := zap.NewProduction()
	url := c.QueryParam("url")
	token := c.Request().Header.Get("Authorization")
	logger.Info("params", zap.Any("url", url), zap.Any("token", token))

	c.Response().Header().Set("HX-Redirect", url)
	return c.String(http.StatusOK, url)
}

func (lh *LoginHandler) HandleSignOut(c echo.Context) error {
	logger, _ := zap.NewProduction()
	logger.Info("Logout")
	expire := time.Now().Add(-7 * 24 * time.Hour)
	cookie := new(http.Cookie)
	cookie.Name = "token"
	cookie.Value = ""
	cookie.Path = "/"
	cookie.Expires = expire
	cookie.HttpOnly = true

	c.SetCookie(cookie)

	ret := `
	<script>
		console.log("signout")
		localStorage.removeItem("token")
		localStorage.removeItem("user")

		setTimeout(() => {
			window.location.replace("/login");
		}, 200)
	</script>
	`
	c.Response().Header().Set("HX-Trigger", "script")
	return c.String(http.StatusOK, ret)
}

func (lh *LoginHandler) HandleAutoLoginPage(c echo.Context) error {
	userToken := c.Get("user").(*jwt.Token)
	token := userToken.Raw
	claims := userToken.Claims.(jwt.MapClaims)
	userGroup := claims["M_UserGroupDashboard"].(string)

	cookie := new(http.Cookie)
	cookie.Name = "token"
	cookie.Value = token
	cookie.Path = "/"
	cookie.HttpOnly = true
	c.SetCookie(cookie)

	var url string
	switch userGroup {
	case "cpone":
		url = "/one-ui"
	case "pic":
		url = "/corp/dashboard_pic"
	case "patient":
		url = "/corp/dashboard_pat"
	default:
		url = "/one-ui"
	}

	redirect := `
	<script>
		setTimeout(() => {
			htmx.ajax('GET', '/login/redirect?url=` + url + `', {
				headers: {
					Authorization: 'Bearer ` + token + `'
				}
			})
		}, 200)
	</script>	
	`
	c.Response().Header().Set("HX-Trigger", "script")
	return c.String(http.StatusOK, redirect)
}
