package main

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"doormile/config"
	"doormile/controllers"
	"doormile/db"
	"doormile/internal/notify"
	"doormile/internal/worker"
	"doormile/middlewares"
	"doormile/migrations"
	"doormile/routes"
	"doormile/utils"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/joho/godotenv"
)

func main() {
	// 1. Load configuration env variables
	_ = godotenv.Load()
	cfg := config.Load()

	utils.Info("Starting Doormile Backend...")

	// 2. Connect to Postgres, Redis & NATS
	db.Connect(cfg)
	db.InitRedis(cfg)
	db.InitNATS(cfg)
	notify.InitFCM()

	// 3. Run GORM migrations for logistics tables
	if db.DB != nil {
		err := migrations.Migrate(db.DB)
		if err != nil {
			utils.Error("⚠️ Migration failed, continuing server boot...", "error", err.Error())
		}
	}

	// 4. Initialize Fiber App
	app := fiber.New(fiber.Config{
		AppName: "Doormile Logistics Service API v1",
	})

	// CORS policy
	app.Use(cors.New(cors.Config{
		AllowHeaders:     "Origin,Content-Type,Accept,Authorization",
		AllowOrigins:     "http://localhost:5173,http://localhost:5174,http://localhost:3000,http://localhost:3001,http://localhost:3002,http://localhost:8080,http://localhost:8081,https://doormile.com,https://www.doormile.com,https://admin.doormile.com,https://api.doormile.com,https://crm.doormile.com,https://console.doormile.com,https://app.doormile.com",
		AllowCredentials: true,
		AllowMethods:     "GET,POST,PUT,DELETE,PATCH,OPTIONS",
	}))

	// Structured Zap logger middleware
	app.Use(middlewares.ZapLogger())

	// 5. Register routes
	routes.RegisterRoutes(app, cfg)

	// 6. Pre-warm Redis pricing cache from Postgres
	controllers.WarmPricingCache()

	// 7. Start NATS booking worker in background
	go worker.StartBookingWorker()

	// 7. Startup server in a background thread
	go func() {
		utils.Info("Server starting", "port", cfg.Port)
		if err := app.Listen(":" + cfg.Port); err != nil {
			utils.Logger.Fatalf("Server failed to bind: %v", err)
		}
	}()

	// Graceful shutdown listener
	gracefulShutdown(app)
}

func gracefulShutdown(app *fiber.App) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)

	<-c
	utils.Info("Shutting down Doormile Backend...")

	// Shutdown fiber
	if err := app.Shutdown(); err != nil {
		utils.Error("Fiber shutdown failed", "error", err)
	}

	// Close database pools
	db.CloseDB()

	time.Sleep(1 * time.Second)
	utils.Info("Shutdown completed cleanly.")
}
