package v1

import (
	"api-service/internal/config"
	"api-service/internal/database"
	healthcheckHandlers "api-service/internal/handlers/healthcheck"
	websocketHandlers "api-service/internal/handlers/websocket"
	"api-service/internal/middleware"
	services "api-service/internal/services/auth"
	websocketServices "api-service/internal/services/websocket"
	"api-service/pkg/logger"
	"time"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

func RegisterRoutes(cfg *config.Config) *gin.Engine {
	router := gin.New()

	// Initialize auth middleware configuration
	middleware.AuthJWTMiddleware()

	// Add global middleware
	router.Use(middleware.CORSConfig())
	router.Use(middleware.ErrorHandler())
	router.Use(logger.RequestLoggerMiddleware(logger.Default()))
	router.Use(gin.Recovery())

	// Initialize services with error handling
	authService := services.NewAuthService(cfg)
	if authService == nil {
		logger.Fatal("Failed to initialize auth service")
	}

	// Initialize database service
	dbService := database.New(cfg)

	// =============================================================================
	// HEALTH CHECK & SYSTEM ROUTES
	// =============================================================================

	healthCheckHandler := healthcheckHandlers.NewHealthCheckHandler(dbService)
	sistem := router.Group("/api/sistem")
	{
		sistem.GET("/health", healthCheckHandler.CheckHealth)
		sistem.GET("/databases", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"databases": dbService.ListDBs(),
				"health":    dbService.Health(),
				"timestamp": time.Now().Unix(),
			})
		})
		sistem.GET("/info", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"service":           "API Service v1.0.0",
				"websocket_active":  true,
				"connected_clients": 0, // TODO: implement websocket handler
				"databases":         dbService.ListDBs(),
				"timestamp":         time.Now().Unix(),
			})
		})
	}

	// =============================================================================
	// SWAGGER DOCUMENTATION
	// =============================================================================

	router.GET("/swagger/*any", ginSwagger.WrapHandler(
		swaggerFiles.Handler,
		ginSwagger.DefaultModelsExpandDepth(-1),
		ginSwagger.DeepLinking(true),
	))

	// =============================================================================
	// WEBSOCKET TEST CLIENT
	// =============================================================================

	// =============================================================================
	// API v1 GROUP
	// =============================================================================

	v1 := router.Group("/api/v1")

	// =============================================================================
	// PUBLIC ROUTES (No Authentication Required)
	// =============================================================================

	// Authentication routes
	// authHandler := authHandlers.NewAuthHandler(authService)
	// tokenHandler := authHandlers.NewTokenHandler(authService)

	// Basic auth routes
	// v1.POST("/auth/login", authHandler.Login)
	// v1.POST("/auth/register", authHandler.Register)
	// v1.POST("/auth/refresh", authHandler.RefreshToken)

	// Token generation routes
	// v1.POST("/token/generate", tokenHandler.GenerateToken)
	// v1.POST("/token/generate-direct", tokenHandler.GenerateTokenDirect)

	// =============================================================================
	// WEBSOCKET ROUTES
	// =============================================================================

	// WebSocket handler will be initialized after websocketHub is defined

	// =============================================================================
	// PUBLISHED ROUTES
	// =============================================================================

	// Initialize WebSocket hub with database service
	websocketHub := websocketServices.NewHub(cfg.WebSocket)
	go websocketHub.Run() // Start WebSocket hub in background

	// Initialize WebSocket handler
	websocketHandler := websocketHandlers.NewWebSocketHandler(websocketHub, cfg.WebSocket)

	// WebSocket routes
	v1.GET("/ws", websocketHandler.HandleWebSocket)
	v1.GET("/ws/test", websocketHandler.TestWebSocketConnection)
	v1.GET("/ws/stats", websocketHandler.GetWebSocketStats)
	v1.POST("/ws/broadcast/qris", websocketHandler.BroadcastQris)
	v1.POST("/ws/broadcast/check", websocketHandler.BroadcastCheck)

	// Retribusi endpoints with WebSocket notifications
	// retribusiHandler := retribusiHandlers.NewRetribusiHandler()
	// retribusiGroup := v1.Group("/retribusi")
	// {
	// 	retribusiGroup.GET("", retribusiHandler.GetRetribusi)
	// 	retribusiGroup.GET("/dynamic", retribusiHandler.GetRetribusiDynamic)
	// 	retribusiGroup.GET("/search", retribusiHandler.SearchRetribusiAdvanced)
	// 	retribusiGroup.GET("/id/:id", retribusiHandler.GetRetribusiByID)

	// 	// POST/PUT/DELETE with automatic WebSocket notifications
	// 	retribusiGroup.POST("", func(c *gin.Context) {
	// 		retribusiHandler.CreateRetribusi(c)

	// 		// Trigger WebSocket notification after successful creation
	// 		if c.Writer.Status() == 200 || c.Writer.Status() == 201 {
	// 			// Notify database change via WebSocket
	// 			// websocketHub.NotifyDatabaseChange("postgres_satudata", "retribusi_changes",
	// 			// 	fmt.Sprintf(`{"action": "created", "timestamp": "%s"}`, time.Now().Format(time.RFC3339)))
	// 		}
	// 	})

	// 	retribusiGroup.PUT("/id/:id", func(c *gin.Context) {
	// 		// id := c.Param("id")
	// 		retribusiHandler.UpdateRetribusi(c)

	// 		// Trigger WebSocket notification after successful update
	// 		if c.Writer.Status() == 200 {
	// 			// Notify database change via WebSocket
	// 			// websocketHub.NotifyDatabaseChange("postgres_satudata", "retribusi_changes",
	// 			// 	fmt.Sprintf(`{"action": "updated", "id": "%s", "timestamp": "%s"}`, id, time.Now().Format(time.RFC3339)))
	// 		}
	// 	})

	// 	retribusiGroup.DELETE("/id/:id", func(c *gin.Context) {
	// 		// id := c.Param("id")
	// 		retribusiHandler.DeleteRetribusi(c)

	// 		// Trigger WebSocket notification after successful deletion
	// 		if c.Writer.Status() == 200 {
	// 			// Notify database change via WebSocket
	// 			// websocketHub.NotifyDatabaseChange("postgres_satudata", "retribusi_changes",
	// 			// 	fmt.Sprintf(`{"action": "deleted", "id": "%s", "timestamp": "%s"}`, id, time.Now().Format(time.RFC3339)))
	// 		}
	// 	})
	// }

	// =============================================================================
	// PROTECTED ROUTES (Authentication Required)
	// =============================================================================

	// Create protected group with configurable authentication
	protected := v1.Group("/")
	protected.Use(middleware.AuthJWTMiddleware()) // Use configurable authentication

	// User profile (protected)
	// protected.GET("/auth/me", authHandler.Me)

	// Retribusi endpoints (CRUD operations - should be protected)
	// protectedQris := protected.Group("/ws")
	// {
	// 	protectedQris.POST("/qris/broadcast", websocketHandler.BroadcastQris)   // POST /api/v1/ws/
	// 	protectedQris.POST("/check/broadcast", websocketHandler.BroadcastCheck) // POST /api/v1/ws/
	// }

	return router
}
