package main

import (
	"bookhoard/internal/app"
	"bookhoard/internal/config"
	"bookhoard/internal/database"
	"bookhoard/internal/handlers"
	"bookhoard/internal/middleware"
	ratelimit "bookhoard/internal/middleware"
	"bookhoard/internal/router"
	"bookhoard/internal/services"
	"bookhoard/internal/sync"
	"context"
	"log"
	"net/http"
	"time"

	"github.com/go-playground/validator/v10"
	"github.com/jackc/pgx/v5/pgxpool"
	"github.com/labstack/echo/v4"
	echomiddleware "github.com/labstack/echo/v4/middleware"
)

// CustomValidator wraps the go-playground validator
type CustomValidator struct {
	validator *validator.Validate
}

func (cv *CustomValidator) Validate(i interface{}) error {
	return cv.validator.Struct(i)
}

// TODO: templates package was removed during router refactor
// This function is unused and should be removed or updated
/*
func getTemplateUserWithTheme(c echo.Context, queries *database.Queries) (templates.User, error) {
	// Get the user from context
	userID := c.Get("user_id")
	if userID == nil {
		return templates.User{}, fmt.Errorf("user not authenticated")
	}

	// Convert to UUID
	userUUID, err := uuid.Parse(userID.(string))
	if err != nil {
		return templates.User{}, fmt.Errorf("invalid user ID: %w", err)
	}

	// Fetch user from database
	userDB, err := queries.GetUser(c.Request().Context(), pgtype.UUID{Bytes: userUUID, Valid: true})
	if err != nil {
		return templates.User{}, err
	}

	userTheme := "tokyo-night"
	if userDB.Theme.Valid {
		userTheme = userDB.Theme.String
	}

	return templates.User{
		ID:       userID,
		Email:    userEmail,
		Username: userUsername,
		Role:     userRole,
		Theme:    userTheme,
	}, nil
}
*/

func main() {
	cfg := config.LoadConfig()

	dbPool, err := pgxpool.New(context.Background(), cfg.DatabaseURL())
	if err != nil {
		log.Fatal("Failed to connect to database:", err)
	}
	defer dbPool.Close()

	queries := database.New(dbPool)

	// Initialize database schema
	log.Println("🔧 Ensuring database schema is initialized...")
	ctx := context.Background()
	if err := database.Initialize(ctx, dbPool); err != nil {
		log.Fatal("❌ Database schema initialization failed:", err)
	}
	log.Println("✅ Database schema initialized and verified, starting server...")

	// Create login attempt tracker: 5 failed attempts = 15 minute lockout
	loginAttemptTracker := ratelimit.NewLoginAttemptTracker(5, 15*time.Minute, 5*time.Minute)

	authHandler := handlers.NewAuthHandler(queries, cfg.JWTSecret, loginAttemptTracker)
	systemSettingsHandler := handlers.NewSystemSettingsHandler(queries)
	libraryHandler := handlers.NewLibraryHandler(queries)
	deviceHandler := handlers.NewDeviceHandler(queries, cfg.JWTSecret, cfg)
	deviceAuthMiddleware := middleware.NewDeviceAuthMiddleware(queries)

	// Create WebSocket connection manager
	connManager := sync.NewConnectionManager()

	// Create sync queue processor
	queueProcessor := sync.NewSyncQueueProcessor(queries)

	// Create library service
	libraryService := services.NewLibraryService(queries)

	// Create worker for background tasks
	worker := services.NewWorker(3)

	koreaderHandler := handlers.NewKOReaderHandler(queries, connManager, queueProcessor)
	wsHandler := handlers.NewWSHandler(queries, connManager, cfg.JWTSecret, deviceAuthMiddleware)
	conflictHandler := handlers.NewConflictHandler(queries, connManager)
	analyticsHandler := handlers.NewAnalyticsHandler(queries)
	queueHandler := handlers.NewQueueHandler(queries, queueProcessor)

	// Create conversion service for EPUB→KEPUB conversion
	conversionService := services.NewConversionService(queries, "/var/bookhoard/cache/kepub")
	opdsHandler := handlers.NewOPDSHandler(queries, conversionService)

	// NEW: Create refactored handlers
	collectionHandler := handlers.NewCollectionHandler(queries, connManager)
	dashboardService := services.NewDashboardService(queries)
	dashboardHandler := handlers.NewDashboardHandler(queries)
	mediaHandler := handlers.NewMediaHandler(queries, libraryService, worker)
	matchingHandler := handlers.NewMatchingHandler(queries, connManager)

	e := echo.New()

	// Set up validator
	v := validator.New()

	// Register custom password complexity validator
	if err := ratelimit.RegisterPasswordValidation(v); err != nil {
		log.Fatal("Failed to register password validator:", err)
	}

	e.Validator = &CustomValidator{validator: v}

	// Middleware
	e.Use(echomiddleware.Logger())
	e.Use(echomiddleware.Recover())
	e.Use(echomiddleware.CORS())
	e.Use(ratelimit.RequestTracingMiddleware(cfg))

	// Rate limiter for auth endpoints
	// rateLimiterConfig := ratelimit.RateLimiterConfig{
	// 	Enabled:           cfg.RateLimitEnabled,
	// 	RequestsPerMinute: cfg.RequestsPerMinute,
	// 	CleanupInterval:   5 * time.Minute,
	// }
	// rateLimiter := ratelimit.NewRateLimiter(rateLimiterConfig)
	// rateLimitMiddleware := ratelimit.RateLimiterMiddleware(rateLimiter) // Now in router/auth.go

	// ========================================================================
	// ROUTER REGISTRATION - Migrate routes to internal/router/ package
	// ========================================================================
	routerConfig := &router.Config{
		Echo:                  e,
		Queries:               queries,
		Cfg:                   cfg,
		DBPool:                dbPool,
		AuthHandler:           authHandler,
		LibraryHandler:        libraryHandler,
		DeviceHandler:         deviceHandler,
		MediaHandler:          mediaHandler,
		MatchingHandler:       matchingHandler,
		KOReaderHandler:       koreaderHandler,
		WSHandler:             wsHandler,
		ConflictHandler:       conflictHandler,
		AnalyticsHandler:      analyticsHandler,
		QueueHandler:          queueHandler,
		CollectionHandler:     collectionHandler,
		DashboardHandler:      dashboardHandler,
		DashboardService:      dashboardService,
		OPDSHandler:           opdsHandler,
		SystemSettingsHandler: systemSettingsHandler,
		ConnManager:           connManager,
		QueueProcessor:        queueProcessor,
		DeviceAuthMiddleware:  deviceAuthMiddleware,
		LoginTracker:          loginAttemptTracker,
	}

	// Register all routes and get ebook handler
	ebookHandler := router.RegisterRoutes(routerConfig)

	// ========================================================================
	// APPLICATION LIFECYCLE MANAGEMENT
	// ========================================================================

	// Create app with lifecycle management
	application := app.New(e, ebookHandler)

	// ========================================================================
	// START SERVER (managed by app lifecycle)
	// ========================================================================

	log.Printf("Starting server on port %s", cfg.ServerPort)

	// Start HTTP server in background
	go func() {
		if err := e.Start(":" + cfg.ServerPort); err != nil && err != http.ErrServerClosed {
			log.Fatalf("Server failed to start: %v", err)
		}
	}()

	// Start application (blocks until shutdown signal)
	if err := application.Start(); err != nil {
		log.Fatalf("Application error: %v", err)
	}
}
