package main

import (
	"context"
	"embed"
	"fmt"
	"html/template"

	"git.keks.cloud/kekskurse/miniauth/pkg/miniauth"
	"git.keks.cloud/kekskurse/miniauth/pkg/smtpclient"
	"git.keks.cloud/kekskurse/miniauth/pkg/userstore"
	"git.keks.cloud/kekskurse/miniauth/pkg/web"
	"github.com/gin-gonic/gin"
	"github.com/rs/zerolog/log"
	"github.com/sethvargo/go-envconfig"
)

//go:embed templates/*
var templatesFS embed.FS

func main() {
	cnf := config()
	router := setupRouter(cnf)
	router.Run(fmt.Sprintf(":%v", cnf.Port))
}

type gloableConfig struct {
	UserStoreConfig userstore.Config        `env:", prefix=USERSTORE_"`
	Port            int                     `env:"PORT, default=8080"`
	SMTPConfig      smtpclient.SMTPConfig   `env:", prefix=SMTP_"`
	WebConfig       web.WebConfig           `env:", prefix=WEB_"`
	MiniauthConfig  miniauth.MiniauthConfig `env:", prefix=MINIAUTH_"`
	DummyDatabase   bool                    `env:"DUMMY_DATABASE"`
}

func config() gloableConfig {
	var c gloableConfig
	err := envconfig.Process(context.Background(), &c)
	if err != nil {
		log.Fatal().Err(err).Msg("cant parse config")
	}

	fmt.Printf("%+v\r\n", c)
	return c
}

func loadTemplates() *template.Template {
	tmpl, err := template.ParseFS(templatesFS, "templates/*.html")
	if err != nil {
		panic(err) // Handle error entsprechend
	}
	return tmpl
}

func setupRouter(cfg gloableConfig) *gin.Engine {
	router := gin.Default()
	router.SetHTMLTemplate(loadTemplates())
	routesWeb := router.Group("/web")

	var us userstore.Store
	var err error
	if cfg.DummyDatabase {
		log.Warn().Msg("Use dummy store")
		us, err = userstore.NewDummyStore()
		if err != nil {
			log.Fatal().Err(err).Msg("cant init dummy store")
		}
	} else {
		us, err = userstore.NewStore(cfg.UserStoreConfig)
		if err != nil {
			log.Fatal().Err(err).Msg("cant init userstore")
		}
	}

	sc := smtpclient.NewSMTPClient(cfg.SMTPConfig)

	ma := miniauth.NewMiniauth(cfg.MiniauthConfig, us, sc)

	webServer := web.NewWeb(cfg.WebConfig, ma)
	webServer.RegisterRoutes(routesWeb)

	router.GET("/", func(c *gin.Context) {})
	router.GET("/ping", func(c *gin.Context) { c.String(200, "pong") })

	return router
}