package main

import (
	"fmt"
	"os"
	"time"

	"git.ex.umbach.dev/Alex/roese-utils/rsconfig"
	"git.ex.umbach.dev/Alex/roese-utils/rslogger"
	"git.ex.umbach.dev/LMS/libcore/models"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/gofiber/websocket/v2"
	"lms.de/backend/modules/config"
	"lms.de/backend/modules/database"
	"lms.de/backend/modules/logger"
	"lms.de/backend/modules/permissions"
	"lms.de/backend/modules/utils"
	"lms.de/backend/routers/router"
	"lms.de/backend/socketserver"
)

func init() {
	fmt.Println("Server is starting...")

	rsconfig.CreateEnvConfigFileIfNotExists(`DEBUG=false
COLORIZED_OUTPUT=true
HOST=127.0.0.1
PORT=8080

LOG_MANAGER_SERVER_URL=http://localhost:50110

# Folder paths
FOLDER_PUBLIC_STATIC=./public/

# MariaDB
MARIADB_HOSTNAME=127.0.0.1
MARIADB_PORT=3306
MARIADB_USERNAME=db_user
MARIADB_PASSWORD=db_password
MARIADB_DATABASE_NAME=db_database_name`)

	config.LoadConfig()

	rslogger.InitLogger(config.Cfg.Debug, config.Cfg.ColorizedOutput, config.Cfg.LogManagerServerUrl)

	if os.Getenv("DOCKER") != "" {
		fmt.Println("Waiting for mariadb docker")
		// waiting for the start of mariadb docker
		time.Sleep(10 * time.Second)
	}

	utils.ValidatorInit()
	database.InitDatabase()
	permissions.InitPermissions()
}

func main() {
	app := fiber.New(fiber.Config{
		BodyLimit: 100 * 1024 * 1024,
	})

	app.Use(cors.New())

	router.SetupRoutes(app)

	app.Use("/ws", func(c *fiber.Ctx) error {
		// IsWebSocketUpgrade returns true if the client
		// requested upgrade to the WebSocket protocol.
		if websocket.IsWebSocketUpgrade(c) {
			sessionId := c.Query("auth")
			// needed for a user who uses multiple tabs in the browser
			// with the same session id because otherwise the last browser
			// tab would subscribe to the topic and the other tabs would
			// not receive any messages
			browserTabSession := c.Query("bts")

			if len(sessionId) != utils.LenHeaderXAuthorization ||
				len(browserTabSession) != utils.LenHeaderXAuthorization {
				return c.SendStatus(fiber.StatusUnauthorized)
			}

			// validate ws session
			var userSession models.UserSession

			database.DB.Select("user_id").First(&userSession, "session = ?", sessionId)

			if userSession.UserId != "" {
				var user models.User

				database.DB.First(&user, "id = ?", userSession.UserId)

				if user.Id != "" {
					c.Locals("sessionId", sessionId)
					c.Locals("browserTabSession", browserTabSession)
					c.Locals("userId", user.Id)
					c.Locals("organizationId", user.OrganizationId)
				}
			}

			return c.Next()
		}

		return fiber.ErrUpgradeRequired
	})

	go socketserver.RunHub()
	socketserver.WebSocketServer(app)

	logger.AddSystemLog(rslogger.LogTypeInfo, "Server started")

	app.Listen(config.Cfg.Host + ":" + config.Cfg.Port)
}
