package http

import (
	"fmt"
	"log"
	"net/http"

	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

	"github.com/UpmeshLTD/urus-aio/service-template/config"
	"github.com/UpmeshLTD/urus-aio/service-template/docs"
	"github.com/UpmeshLTD/urus-aio/service-template/server/http/router"
	"github.com/UpmeshLTD/urus-aio/service-template/service"
	"github.com/gin-gonic/gin"
	"go.opencensus.io/plugin/ochttp"
)

//go:generate mockery --name=Server --inpackage --case=snake
type Server interface {
	Serve() error
}

type serverImpl struct {
	server *http.Server
	svc    service.Service
	config config.Config
}

func NewServer(svc service.Service, config config.Config) Server {
	i := &serverImpl{
		svc:    svc,
		config: config,
	}

	i.initServer()
	return i
}

func (i *serverImpl) Serve() error {
	log.Printf(" 🚀 Listening HTTP on port %d", i.config.GetHTTPConfig().Port)
	return i.server.ListenAndServe()
}

func (i *serverImpl) initServer() {
	gin.SetMode(i.config.GetHTTPConfig().Mode)
	r := i.initRouter()

	srv := &http.Server{
		Addr: fmt.Sprintf(":%d", i.config.GetHTTPConfig().Port),
		Handler: &ochttp.Handler{
			Handler:          r,
			IsPublicEndpoint: true,
		},
	}
	i.server = srv
}

func (i *serverImpl) initRouter() *gin.Engine {
	r := router.New()

	i.registerRoutes(r)

	i.initSwagger()
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	return r
}
func (i *serverImpl) initSwagger() {
	docs.SwaggerInfo.Host = i.config.GetSwaggerConfig().Host
	docs.SwaggerInfo.BasePath = i.config.GetSwaggerConfig().BasePath
}

func (i *serverImpl) registerRoutes(r *gin.Engine) {
	r.GET("/", i.svc.NewGetInfo())
	r.GET("/health-check", i.svc.NewHealthCheck())

	// TODO: enable if need authentication
	// -------- Authentication --------
	//userRoutes := r.Group("")
	//store := cookie.NewStore([]byte("secret"))
	//userRoutes.Use(sessions.Sessions("session", store))
	//userMiddleware := middleware.NewSellerAuthMiddleware(i.config.GetAuthConfig().User.Host, i.config.GetAuthConfig().User.Port)
	//userRoutes.Use(userMiddleware)
	// --------------------------------

}
