package httpserver

import (
	"fmt"
	"log/slog"

	"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/currency"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/league"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
	referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
	virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame"
	alea "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/Alea"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
	jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
	customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"

	notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
	"github.com/bytedance/sonic"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
)

type App struct {
	currSvc                *currency.Service
	fiber                  *fiber.App
	aleaVirtualGameService alea.AleaVirtualGameService
	veliVirtualGameService veli.VeliVirtualGameService
	recommendationSvc      recommendation.RecommendationService
	cfg                    *config.Config
	logger                 *slog.Logger
	NotidicationStore      *notificationservice.Service
	referralSvc            referralservice.ReferralStore
	port                   int
	authSvc                *authentication.Service
	userSvc                *user.Service
	betSvc                 *bet.Service
	virtualGameSvc         virtualgameservice.VirtualGameService
	reportSvc              *report.Service
	chapaSvc               *chapa.Service
	walletSvc              *wallet.Service
	transactionSvc         *transaction.Service
	ticketSvc              *ticket.Service
	branchSvc              *branch.Service
	companySvc             *company.Service
	validator              *customvalidator.CustomValidator
	JwtConfig              jwtutil.JwtConfig
	Logger                 *slog.Logger
	prematchSvc            *odds.ServiceImpl
	eventSvc               event.Service
	leagueSvc              league.Service
	resultSvc              *result.Service
}

func NewApp(
	currSvc *currency.Service,
	port int, validator *customvalidator.CustomValidator,
	authSvc *authentication.Service,
	logger *slog.Logger,
	JwtConfig jwtutil.JwtConfig,
	userSvc *user.Service,
	ticketSvc *ticket.Service,
	betSvc *bet.Service,
	reportSvc *report.Service,
	chapaSvc *chapa.Service,
	walletSvc *wallet.Service,
	transactionSvc *transaction.Service,
	branchSvc *branch.Service,
	companySvc *company.Service,
	notidicationStore *notificationservice.Service,
	prematchSvc *odds.ServiceImpl,
	eventSvc event.Service,
	leagueSvc league.Service,
	referralSvc referralservice.ReferralStore,
	virtualGameSvc virtualgameservice.VirtualGameService,
	aleaVirtualGameService alea.AleaVirtualGameService,
	veliVirtualGameService veli.VeliVirtualGameService,
	recommendationSvc recommendation.RecommendationService,
	resultSvc *result.Service,
	cfg *config.Config,
) *App {
	app := fiber.New(fiber.Config{
		CaseSensitive:            true,
		DisableHeaderNormalizing: true,
		JSONEncoder:              sonic.Marshal,
		JSONDecoder:              sonic.Unmarshal,
	})

	app.Use(cors.New(cors.Config{
		AllowOrigins: "*",
		AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
		AllowHeaders: "Content-Type,Authorization,platform",
		// AllowCredentials: true,
	}))

	s := &App{
		currSvc:                currSvc,
		fiber:                  app,
		port:                   port,
		authSvc:                authSvc,
		validator:              validator,
		logger:                 logger,
		JwtConfig:              JwtConfig,
		userSvc:                userSvc,
		ticketSvc:              ticketSvc,
		betSvc:                 betSvc,
		reportSvc:              reportSvc,
		chapaSvc:               chapaSvc,
		walletSvc:              walletSvc,
		transactionSvc:         transactionSvc,
		branchSvc:              branchSvc,
		companySvc:             companySvc,
		NotidicationStore:      notidicationStore,
		referralSvc:            referralSvc,
		Logger:                 logger,
		prematchSvc:            prematchSvc,
		eventSvc:               eventSvc,
		leagueSvc:              leagueSvc,
		virtualGameSvc:         virtualGameSvc,
		aleaVirtualGameService: aleaVirtualGameService,
		veliVirtualGameService: veliVirtualGameService,
		recommendationSvc:      recommendationSvc,
		resultSvc:              resultSvc,
		cfg:                    cfg,
	}

	s.initAppRoutes()

	return s
}

func (a *App) Run() error {
	return a.fiber.Listen(fmt.Sprintf(":%d", a.port))
}
