// cmd/server/main.go - ENHANCED WITH DEBUG LOGGING
package main

import (
	"context"
	"log"
	"lost-and-found/internal/config"
	"lost-and-found/internal/middleware"
	"lost-and-found/internal/routes"
	"lost-and-found/internal/workers"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
	"sync"

	"github.com/gin-gonic/gin"
	"github.com/joho/godotenv"
	"go.uber.org/zap"
)

func main() {
	// Load .env file
	if err := godotenv.Load(); err != nil {
		log.Println("⚠️ No .env file found, using environment variables")
	}

	// ✅ Structured Logging
	logger, err := zap.NewProduction()
	if err != nil {
		log.Fatalf("❌ Failed to initialize logger: %v", err)
	}
	defer logger.Sync()

	logger.Info("🚀 Starting Lost & Found System...")

	// Initialize JWT config
	config.InitJWT()
	logger.Info("✅ JWT configuration initialized")

	// Initialize database
	logger.Info("📊 Initializing database...")
	if err := config.InitDB(); err != nil {
		logger.Fatal("❌ Failed to initialize database", zap.Error(err))
	}
	defer func() {
		logger.Info("🗄️ Closing database connections...")
		if err := config.CloseDB(); err != nil {
			logger.Error("Failed to close database", zap.Error(err))
		} else {
			logger.Info("✅ Database connections closed")
		}
	}()

	// Run migrations
	logger.Info("📋 Running migrations...")
	db := config.GetDB()
	if err := config.RunMigrations(db); err != nil {
		logger.Fatal("❌ Failed to run migrations", zap.Error(err))
	}

	// Initialize Gin
	if config.IsProduction() {
		gin.SetMode(gin.ReleaseMode)
	}
	router := gin.Default()

	// Apply middleware
	router.Use(middleware.CORSMiddleware())
	router.Use(middleware.LoggerMiddleware())
	router.Use(middleware.RateLimiterMiddleware())

	if config.IsDevelopment() {
        router.Use(func(c *gin.Context) {
            c.Writer.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
            c.Writer.Header().Set("Pragma", "no-cache")
            c.Writer.Header().Set("Expires", "0")
            c.Next()
        })
    }

	// Serve static files
	router.Static("/uploads", "./uploads")
	router.Static("/css", "./web/css")
	router.Static("/js", "./web/js")
	router.Static("/assets", "./web/assets")

// Frontend routes
router.GET("/", func(c *gin.Context) { c.File("./web/index.html") })
router.GET("/login", func(c *gin.Context) { c.File("./web/login.html") })
router.GET("/login.html", func(c *gin.Context) { c.File("./web/login.html") }) // ✅ Tambahkan ini
router.GET("/register", func(c *gin.Context) { c.File("./web/register.html") })
router.GET("/register.html", func(c *gin.Context) { c.File("./web/register.html") }) // ✅ Tambahkan ini
router.GET("/admin", func(c *gin.Context) { c.File("./web/admin.html") })
router.GET("/admin.html", func(c *gin.Context) { c.File("./web/admin.html") }) // ✅ Tambahkan ini
router.GET("/manager", func(c *gin.Context) { c.File("./web/manager.html") })
router.GET("/manager.html", func(c *gin.Context) { c.File("./web/manager.html") }) // ✅ Tambahkan ini
router.GET("/user", func(c *gin.Context) { c.File("./web/user.html") })
router.GET("/user.html", func(c *gin.Context) { c.File("./web/user.html") }) // ✅ Tambahkan ini

	// Setup API routes
	routes.SetupRoutes(router, db, logger)
	logger.Info("✅ API routes configured")

	// ✅ Start Background Workers
	logger.Info("🔄 Starting background workers...")
	expireWorker := workers.NewExpireWorker(db)
	auditWorker := workers.NewAuditWorker(db)
	matchingWorker := workers.NewMatchingWorker(db)
	notificationWorker := workers.NewNotificationWorker(db)

// ✅ Background Workers - 4 Goroutines
	expireWorker.Start()
	auditWorker.Start()
	matchingWorker.Start()
	notificationWorker.Start()
	logger.Info("✅ All background workers started")

	// Get server config
	serverConfig := config.GetServerConfig()
	port := serverConfig.Port

	// ✅ DEBUG: Print sebelum create server
	log.Println("🔧 DEBUG: Creating HTTP server...")
	log.Printf("🔧 DEBUG: Port = %s\n", port)
	log.Printf("🔧 DEBUG: Address = :%s\n", port)

	// ✅ HTTP Server with Timeouts
	srv := &http.Server{
		Addr:         ":" + port,
		Handler:      router,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
		IdleTimeout:  60 * time.Second,
	}

	// ✅ DEBUG: Print sebelum start goroutine
	log.Println("🔧 DEBUG: Starting server goroutine...")

	// ✅ Start server in goroutine
	serverErrors := make(chan error, 1)
	go func() {
		// ✅ PENTING: Print ini HARUS muncul
		log.Println("🚀 Server starting...")
		log.Printf("   📍 URL:  http://localhost:%s\n", port)
		log.Printf("   📡 API:  http://localhost:%s/api\n", port)
		log.Printf("   🌍 ENV:  %s\n", serverConfig.Environment)
		log.Println("✨ Press Ctrl+C to stop")
		log.Println("🔧 DEBUG: Calling srv.ListenAndServe()...")
		
		logger.Info("🚀 Server starting",
			zap.String("url", "http://localhost:"+port),
			zap.String("api", "http://localhost:"+port+"/api"),
			zap.String("environment", serverConfig.Environment),
		)

		// ✅ Ini yang benar-benar mulai server
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Printf("❌ SERVER ERROR: %v\n", err)
			serverErrors <- err
		}
	}()

	// ✅ DEBUG: Print setelah goroutine
	log.Println("🔧 DEBUG: Server goroutine launched, waiting for signals...")

	// ✅ Wait for interrupt signal OR server error
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	select {
	case sig := <-quit:
		logger.Info("🛑 Shutdown signal received", zap.String("signal", sig.String()))
	case err := <-serverErrors:
		logger.Fatal("❌ Server error", zap.Error(err))
	}

	logger.Info("🔄 Starting graceful shutdown...")

	// ✅ Step 1: Create shutdown context with timeout
	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer shutdownCancel()

	// Implementasi ACID dan Kontrol Transaksi (15%)
	// ✅ Step 2: Stop accepting new HTTP requests
	// Implementasi Graceful Shutdown dengan srv.Shutdown(shutdownCtx) memastikan Durability data yang sedang diproses.
	logger.Info("🔌 Stopping server from accepting new requests...")
	if err := srv.Shutdown(shutdownCtx); err != nil {
		logger.Error("⚠️ Server forced to shutdown", zap.Error(err))
	} else {
		logger.Info("✅ Server stopped accepting new requests")
	}

	// ✅ Step 3: Stop background workers
	logger.Info("🔄 Stopping background workers...")
	
	workersDone := make(chan struct{})
	
	go func() {
		var wg sync.WaitGroup
		
		wg.Add(4)
		
		go func() {
			defer wg.Done()
			expireWorker.Stop()
			logger.Info("✅ Expire worker stopped")
		}()
		
		go func() {
			defer wg.Done()
			auditWorker.Stop()
			logger.Info("✅ Audit worker stopped")
		}()
		
		go func() {
			defer wg.Done()
			matchingWorker.Stop()
			logger.Info("✅ Matching worker stopped")
		}()
		
		go func() {
			defer wg.Done()
			notificationWorker.Stop()
			logger.Info("✅ Notification worker stopped")
		}()

		wg.Wait()
		close(workersDone)
	}()

	// ✅ Wait for workers or timeout
	select {
	case <-workersDone:
		logger.Info("✅ All background workers stopped gracefully")
	case <-shutdownCtx.Done():
		logger.Warn("⚠️ Worker shutdown timeout exceeded, forcing exit")
	}

	logger.Info("✅ Graceful shutdown completed")
	logger.Info("👋 Goodbye!")
}