package webpage

import (
	"database/sql"
	"embed"
	"git.keks.cloud/kekskurse/go-sample-webpage/pkg/user"
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/jwtauth/v5"
	"github.com/golang-migrate/migrate/v4"
	"github.com/golang-migrate/migrate/v4/database/mysql"
	"github.com/golang-migrate/migrate/v4/source/iofs"
	"github.com/rs/zerolog/log"
	"github.com/unrolled/render"
	"github.com/urfave/cli/v2"
	"net/http"
	"os"
)

type WebPageConfig struct {
	Commands []*cli.Command
	Templates embed.FS
	Static embed.FS
	Migrations embed.FS
	Bootstrap func(bootstrapConfig BootstrapConfig)
}

type BootstrapConfig struct {
	Router chi.Router
	Token *jwtauth.JWTAuth
	UserClient user.UserClient
}

var config WebPageConfig

func RunWebApp(cfg WebPageConfig)  {
	config = cfg
	commands := config.Commands
	commands = append(commands, &cli.Command{
		Name:    "run",
		//Aliases: []string{"c"},
		Usage:   "Run Webapplication",
		Action:  func(c *cli.Context) error {
			return runWebpage()
		},
	}, &cli.Command{
		Name:    "migrate",
		//Aliases: []string{"c"},
		Usage:   "Run Migration Scripts",
		Action:  func(c *cli.Context) error {
			return runMigration()
		},
	})

	app := &cli.App{
		Name: "Webpage",
		Usage: "Sample Webapplication in golang",
		Commands: commands,
	}


	err := app.Run(os.Args)
	if err != nil {
		log.Fatal().Err(err).Msg("Cant run application")
	}
}


func runWebpage() error {
	r := chi.NewRouter()
	render := render.New(render.Options{
		FileSystem: &render.EmbedFileSystem{
			FS: config.Templates,
		},
	})
	r.Use(middleware.Logger)

	r.Handle("/static/*", http.FileServer(http.FS(config.Static)))
	r.Group(func(r chi.Router) {
		r.Use(TemplateMiddelware)
		r.Get("/", func(w http.ResponseWriter, r *http.Request) {
			render.HTML(w, http.StatusOK, "index", map[string]string {"title": "Soeren"})
		})

		tokenAuth := jwtauth.New("HS256", []byte("secret"), nil)
		uc := user.GetUserClient()

		config.Bootstrap(BootstrapConfig{
			Router:     r,
			Token:      tokenAuth,
			UserClient: uc,
		})
	})


	http.ListenAndServe(":3000", r) //todo; handle this error
	return nil
}

func runMigration() error {
	log.Debug().Msg("Start Migration")
	db, err := sql.Open("mysql", "root:test@tcp(localhost:3306)/test?multiStatements=true")
	if err != nil {
		log.Fatal().Err(err).Msg("Cant connect to Database")
	}

	d, err := iofs.New(config.Migrations, "database/migrations")

	if err != nil {
		log.Fatal().Err(err).Msg("Cant create iofs")
	}

	driver, err := mysql.WithInstance(db, &mysql.Config{})

	if err != nil {
		log.Fatal().Err(err).Msg("Cant create driver")
	}

	m, err := migrate.NewWithInstance(
		"iofs", d,
		"test", driver)

	if err != nil {
		log.Fatal().Err(err).Msg("Cant create migration object")
	}

	err = m.Up()
	if err != nil {
		log.Error().Err(err).Msg("Cant execute Migrations")
		return err
	}
	log.Info().Msg("Execute Migrations")
	return nil
}