package main

import (
	_ "sno/docs" // docs is generated by Swag CLI

	"log"
	"sno/internal/config"
	"sno/internal/database"
	"sno/internal/handlers"
	"sno/internal/repository"
	"sno/internal/routes"
	"sno/internal/service"
	"sno/internal/redis"

	"github.com/gofiber/fiber/v2"
	fiberSwagger "github.com/swaggo/fiber-swagger"
)

// @title Telegram Quiz Mini App API
// @version 1.0
// @description API для Telegram Mini App с викторинами, QR-сканированием и внутренней валютой

// @host localhost:8080
// @BasePath /

// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization

// @securityDefinitions.basic BasicAuth

func main() {
	// 1. Load configuration
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("Failed to load configuration: %v", err)
	}

	// 2. Connect to the database
	dbPool, err := database.Connect(cfg.DatabaseURL)
	if err != nil {
		log.Fatalf("Failed to connect to database: %v", err)
	}

	// Connect to Redis
	redisClient, err := redis.Connect(cfg.RedisURL)
	if err != nil {
		log.Fatalf("Failed to connect to Redis: %v", err)
	}

	// 3. Initialize layers
	// Repositories
	quizRepo := repository.NewQuizRepository(dbPool)
	questionRepo := repository.NewQuestionRepository(dbPool)
	userRepo := repository.NewUserRepository(dbPool)
	quizAttemptRepo := repository.NewQuizAttemptRepository(dbPool)
	rewardRepo := repository.NewRewardRepository(dbPool)
	purchaseRepo := repository.NewPurchaseRepository(dbPool)
	qrScanRepo := repository.NewQRScanRepository(dbPool)
	adminRepo := repository.NewAdminRepository(dbPool)

	// Services
	userService := service.NewUserService(userRepo, purchaseRepo, quizAttemptRepo)
	quizService := service.NewQuizService(dbPool, quizRepo, questionRepo, userRepo, userService, quizAttemptRepo)
	questionService := service.NewQuestionService(questionRepo)
	rewardService := service.NewRewardService(dbPool, rewardRepo, userRepo, purchaseRepo)
	adminService := service.NewAdminService(userRepo, adminRepo, redisClient)
	qrService := service.NewQRService(qrScanRepo, adminService, quizService, redisClient)

	// Handlers
	quizHandler := handlers.NewQuizHandler(quizService, userService)
	questionHandler := handlers.NewQuestionHandler(questionService)
	rewardHandler := handlers.NewRewardHandler(rewardService)
	userHandler := handlers.NewUserHandler(userService)
	adminHandler := handlers.NewAdminHandler(adminService, qrService)
	qrHandler := handlers.NewQRHandler(qrService)
	authHandler := handlers.NewAuthHandler(cfg.BotToken, userService, adminService)

	// 4. Create a new Fiber app
	app := fiber.New()

	// Swagger documentation
	app.Get("/swagger/*", fiberSwagger.WrapHandler)

	// 5. Setup routes
	routes.Setup(app, quizHandler, questionHandler, rewardHandler, userHandler, adminHandler, qrHandler, authHandler, adminService, cfg.BotToken)

	// 6. Start the server
	log.Printf("Server is starting on port %s...", cfg.Port)
	err = app.Listen(":" + cfg.Port)
	if err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}
