package ginserver

import (
	"net/http"
	"nos-comptes/handler"
	"nos-comptes/internal/account"
	"nos-comptes/internal/expense"
	sharedaccount "nos-comptes/internal/shared-account"
	"nos-comptes/internal/storage/dao/postgresql"
	"nos-comptes/internal/user"
	"time"

	"github.com/gin-gonic/gin"

	"github.com/gin-contrib/cors"
)

func NewRouter(config *handler.Config) *gin.Engine {
	gin.SetMode(gin.ReleaseMode)

	router := gin.New()
	router.HandleMethodNotAllowed = true

	router.Use(cors.New(cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"*"},
		AllowHeaders:     []string{"*"},
		ExposeHeaders:    []string{"*"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	}))
	router.Use(gin.Recovery())
	router.Use(GetLoggerMiddleware())
	router.Use(GetHTTPLoggerMiddleware())

	db := postgresql.NewDatabasePostgreSQL(config.DBConnectionURI)
	hc := handler.NewContext()
	uh := user.NewHandler(hc, db)
	ah := account.NewHandler(hc, db)
	sah := sharedaccount.NewHandler(hc, db)
	eh := expense.NewHandler(hc, db)

	public := router.Group("/")
	public.Handle(http.MethodGet, "/_health", hc.GetHealth)

	userRoute := public.Group("/users")
	userRoute.Handle("LOGIN", "", uh.ConnectUser)
	userRoute.Handle(http.MethodPost, "", uh.CreateUser)

	securedUserRoute := userRoute.Group("")
	//TODO add secure auth
	securedUserRoute.Handle(http.MethodGet, "/:userId", uh.GetUser)
	// end: user routes

	securedAccountRoute := securedUserRoute.Group("/:userId/accounts")
	//account route
	securedAccountRoute.Handle(http.MethodGet, "/", ah.GetAllAccountOfUser)
	securedAccountRoute.Handle(http.MethodPost, "/:accountId", ah.CreateAccountOfUser)
	securedAccountRoute.Handle(http.MethodDelete, "/:accountId", ah.DeleteAccountOfUser)
	securedAccountRoute.Handle(http.MethodGet, "/", ah.GetSpecificAccountOfUser)

	securedSharedAccountRoute := securedUserRoute.Group("/:userId/sharedaccounts")
	//shared route
	securedSharedAccountRoute.Handle(http.MethodPost, "/:accountId", sah.ShareAnAccount)
	securedSharedAccountRoute.Handle(http.MethodDelete, "/:accountId", sah.DeleteSharedAccount)
	securedSharedAccountRoute.Handle(http.MethodGet, "/", sah.GetAllSharedAccountOfUser)
	securedSharedAccountRoute.Handle(http.MethodGet, "/:sharedAccountId", sah.GetSpecificSharedAccountOfUser)

	securedExpenseRoute := securedUserRoute.Group("/:userId/accounts/:accountId/expenses")
	//expense route
	securedExpenseRoute.Handle(http.MethodPost, "/", eh.CreateAnExpense)
	securedExpenseRoute.Handle(http.MethodDelete, "/:expenseId", eh.DeleteExpense)
	securedExpenseRoute.Handle(http.MethodGet, "/", eh.GetAllExpenses)
	securedExpenseRoute.Handle(http.MethodGet, "/:expenseId", eh.GetAnExpenses)
	return router
}
