package fiber

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/limiter"
	jwt "github.com/gofiber/jwt/v3"

	adminHandler "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/service/handler/admin"
)

func initAdminHandlers(app *fiber.App, sp ServiceProvider) {
	admin := app.Group("/admin", jwt.New(getJWTConfig(sp)))

	admin.Get(
		"/",
		adminHandler.NewArticleListPageHandler(
			sp.ArticleRepository(),
		),
	)

	admin.All("/login", limiter.New(limiter.Config{
		Max:        int(sp.ConfigService().LoginRateLimiterMaxRequests()),
		Expiration: sp.ConfigService().LoginRateLimiterExpiration(),
	}), adminHandler.NewLoginPageHandler(
		sp.ConfigService(),
		sp.AuthService(),
		sp.UserRepository(),
	))

	admin.All(
		"/logout",
		adminHandler.NewLogoutPageHandler(
			sp.ConfigService(),
		),
	)

	admin.All(
		"/user/change-password",
		adminHandler.NewChangePasswordPageHandler(
			sp.AuthService(),
			sp.UserRepository(),
		),
	)

	admin.All(
		"/article/add",
		adminHandler.NewAddArticlePageHandler(
			sp.TransactionManager(),
			sp.ArticleRepository(),
			sp.TagRepository(),
			sp.ArticleTagRepository(),
			sp.LanguageRepository(),
			sp.CacheService(),
		),
	)

	admin.All(
		"/article/edit/:id<int>",
		adminHandler.NewEditArticlePageHandler(
			sp.TransactionManager(),
			sp.ArticleRepository(),
			sp.TagRepository(),
			sp.ArticleTagRepository(),
			sp.LanguageRepository(),
			sp.CacheService(),
		),
	)

	admin.All(
		"/article/delete/:id<int>",
		adminHandler.NewDeleteArticlePageHandler(
			sp.TransactionManager(),
			sp.ArticleRepository(),
			sp.ArticleTagRepository(),
			sp.CacheService(),
		),
	)

	admin.Get(
		"/tag",
		adminHandler.NewTagListPageHandler(
			sp.TagRepository(),
		),
	)

	admin.All(
		"/tag/add",
		adminHandler.NewAddTagPageHandler(
			sp.TagRepository(),
		),
	)

	admin.All(
		"/tag/edit/:id<int>",
		adminHandler.NewEditTagPageHandler(
			sp.TagRepository(),
			sp.LanguageRepository(),
			sp.CacheService(),
		),
	)

	admin.All(
		"/tag/delete/:id<int>",
		adminHandler.NewDeleteTagPageHandler(
			sp.TagRepository(),
			sp.LanguageRepository(),
			sp.CacheService(),
		),
	)
}

// nolint
func getJWTConfig(sp ServiceProvider) jwt.Config {
	return jwt.Config{
		SigningKey:  []byte(sp.ConfigService().JWTSecretKey()),
		TokenLookup: "cookie:" + sp.ConfigService().JWTCookie(),
		ErrorHandler: func(fctx *fiber.Ctx, err error) error {
			return fctx.Redirect("/admin/login")
		},
		Filter: func(fctx *fiber.Ctx) bool {
			method := fctx.Method()
			path := fctx.Path()

			if method != fiber.MethodGet && method != fiber.MethodPost &&
				method != fiber.MethodPut && method != fiber.MethodDelete {
				return true
			}

			if path == "/admin/login" {
				return true
			}

			return false
		},
	}
}
