package httpserver

import (
	"fmt"
	agentkindboxservice "git.gocasts.ir/ebhomengo/niki/service/agent/kind_box"
	agentkindboxvalidator "git.gocasts.ir/ebhomengo/niki/validator/agent/kind_box"

	config "git.gocasts.ir/ebhomengo/niki/config"
	adminhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/admin"
	adminKindBoxHandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/kind_box"
	adminkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/kind_box_req"
	agentkindboxhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/agent/kind_box"
	benefactoraddresshandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/address"
	benefactorhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/benefactor"
	benefactorkindboxhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/kind_box"
	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"
	adminkindboxservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box"
	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"
	benefactorkindboxservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box"
	benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
	adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin"
	adminkindboxvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/kind_box"
	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"
	benefactorkindboxvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box"
	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
	benefactorKindBoxHandler    benefactorkindboxhandler.Handler
	adminHandler                adminhandler.Handler
	adminKindBoxReqHandler      adminkindboxreqhandler.Handler
	adminKindBoxHandler         adminKindBoxHandler.Handler
	agentKindBoxHandler         agentkindboxhandler.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,
	benefactorKindBoxSvc benefactorkindboxservice.Service,
	benefactorKindBoxVld benefactorkindboxvalidator.Validator,
	adminSvc adminservice.Service,
	adminVld adminvalidator.Validator,
	adminAuthSvc authservice.Service,
	adminKinBoxReqSvc adminkindboxreqservice.Service,
	adminKinBoxReqVld adminkindboxreqvalidator.Validator,
	adminAuthorizeSvc adminauthorizationservice.Service,
	adminKindBoxSvc adminkindboxservice.Service,
	adminKindBoxVld adminkindboxvalidator.Validator,
	agentKindBoxSvc agentkindboxservice.Service,
	agentKindBoxVld agentkindboxvalidator.Validator,
) 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),
		benefactorKindBoxHandler:    benefactorkindboxhandler.New(cfg.Auth, benefactorAuthSvc, benefactorKindBoxSvc, benefactorKindBoxVld),
		adminHandler:                adminhandler.New(cfg.AdminAuth, adminAuthSvc, adminSvc, adminVld, adminAuthorizeSvc),
		adminKindBoxReqHandler:      adminkindboxreqhandler.New(cfg.Auth, adminAuthSvc, adminKinBoxReqSvc, adminKinBoxReqVld, adminAuthorizeSvc),
		adminKindBoxHandler:         adminKindBoxHandler.New(cfg.Auth, adminAuthSvc, adminKindBoxSvc, adminKindBoxVld, adminAuthorizeSvc),
		agentKindBoxHandler:         agentkindboxhandler.New(cfg.AdminAuth, adminAuthSvc, agentKindBoxSvc, agentKindBoxVld, 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.benefactorKindBoxHandler.SetRoutes(s.Router)
	s.adminHandler.SetRoutes(s.Router)
	s.adminKindBoxReqHandler.SetRoutes(s.Router)
	s.adminKindBoxHandler.SetRoutes(s.Router)
	s.agentKindBoxHandler.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)
}