package httpserver

import (
	"fmt"
	config "git.gocasts.ir/ebhomengo/niki/config"
	adminhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/admin"
	adminkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/kind_box_req"
	benefactoraddresshandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/address"
	benefactorhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/benefactor"
	benefactorkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/kind_box_req"
	"git.gocasts.ir/ebhomengo/niki/docs"
	adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin"
	adminauthorizationservice "git.gocasts.ir/ebhomengo/niki/service/admin/authorization"
	adminkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box_req"
	authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
	benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address"
	benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
	benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
	adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin"
	adminkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/kind_box_req"
	benefactoraddressvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/address"
	benefactorvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/benefactor"
	benefactorkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box_req"
	echo "github.com/labstack/echo/v4"
	middleware "github.com/labstack/echo/v4/middleware"
	echoSwagger "github.com/swaggo/echo-swagger"
)

type Server struct {
	config                      config.Config
	Router                      *echo.Echo
	benefactorHandler           benefactorhandler.Handler
	benefactorKindBoxReqHandler benefactorkindboxreqhandler.Handler
	benefactorAddressHandler    benefactoraddresshandler.Handler
	adminHandler                adminhandler.Handler
	adminKindBoxReqHandler      adminkindboxreqhandler.Handler
}

func New(
	cfg config.Config,
	benefactorSvc benefactorservice.Service,
	benefactorVld benefactorvalidator.Validator,
	benefactorAuthSvc authservice.Service,
	benefactorKindBoxReqSvc benefactorkindboxreqservice.Service,
	benefactorKindBoxReqVld benefactorkindboxreqvalidator.Validator,
	benefactorAddressSvc benefactoraddressservice.Service,
	benefactorAddressVld benefactoraddressvalidator.Validator,
	adminSvc adminservice.Service,
	adminVld adminvalidator.Validator,
	adminAuthSvc authservice.Service,
	adminKinBoxReqSvc adminkindboxreqservice.Service,
	adminKinBoxReqVld adminkindboxreqvalidator.Validator,
	adminAuthorizeSvc adminauthorizationservice.Service,
) Server {
	return Server{
		Router:                      echo.New(),
		config:                      cfg,
		benefactorHandler:           benefactorhandler.New(cfg.Auth, benefactorAuthSvc, benefactorSvc, benefactorVld),
		benefactorKindBoxReqHandler: benefactorkindboxreqhandler.New(cfg.Auth, benefactorAuthSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld),
		benefactorAddressHandler:    benefactoraddresshandler.New(cfg.Auth, benefactorAuthSvc, benefactorAddressSvc, benefactorAddressVld),
		adminHandler:                adminhandler.New(cfg.AdminAuth, adminAuthSvc, adminSvc, adminVld, adminAuthorizeSvc),
		adminKindBoxReqHandler:      adminkindboxreqhandler.New(cfg.Auth, adminAuthSvc, adminKinBoxReqSvc, adminKinBoxReqVld, adminAuthorizeSvc),
	}
}

func (s Server) Serve() {
	s.Router.Use(middleware.RequestID())
	s.Router.Use(middleware.Recover())
	RegisterSwagger(s.Router, s.config)

	// Routes
	s.Router.GET("/health-check", s.healthCheck)
	s.benefactorHandler.SetRoutes(s.Router)
	s.benefactorKindBoxReqHandler.SetRoutes(s.Router)
	s.benefactorAddressHandler.SetRoutes(s.Router)
	s.adminHandler.SetRoutes(s.Router)
	s.adminKindBoxReqHandler.SetRoutes(s.Router)
	// Start server
	address := fmt.Sprintf(":%d", s.config.HTTPServer.Port)
	fmt.Printf("start echo server on %s\n", address)
	if err := s.Router.Start(address); err != nil {
		fmt.Println("router start error", err)
	}
}

func RegisterSwagger(s *echo.Echo, config config.Config) {
	//TODO: move this to a better place and make it more dynamic and configurable
	docs.SwaggerInfo.Title = "NIKI API"
	docs.SwaggerInfo.Description = "This is the API documentation for the NIKI project"
	docs.SwaggerInfo.Version = "1.0.0"
	//docs.SwaggerInfo.BasePath = "/api/v1"
	docs.SwaggerInfo.Host = fmt.Sprintf("localhost:%d", config.HTTPServer.Port)

	s.GET("/swagger/*any", echoSwagger.WrapHandler)
}