package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-migrate/migrate/v4"
	_ "github.com/golang-migrate/migrate/v4/database/postgres"
	_ "github.com/golang-migrate/migrate/v4/source/file"

	"ems-backend/db"
	"ems-backend/models"
	"ems-backend/routes"
	"ems-backend/services"
	"ems-backend/utils"
)

func initSchema() {
	// Construct DB URL from env vars or use a default one suitable for the container environment
	// Expected format: postgres://user:password@host:port/dbname?sslmode=disable
	dbUser := os.Getenv("POSTGRES_USER")
	if dbUser == "" { dbUser = "ems" }
	dbPass := os.Getenv("DB_PASSWORD") // Note: inconsistent naming in env, checking plan
	if dbPass == "" { dbPass = "ems_pass" } // Fallback
	dbHost := os.Getenv("POSTGRES_HOST")
	if dbHost == "" { dbHost = "postgres" }
	dbPort := os.Getenv("POSTGRES_PORT")
	if dbPort == "" { dbPort = "5432" }
	dbName := os.Getenv("POSTGRES_DB")
	if dbName == "" { dbName = "ems" }

	// If DB_PASSWORD env var is not set but POSTGRES_PASSWORD is (from docker-compose)
	if dbPass == "ems_pass" && os.Getenv("POSTGRES_PASSWORD") != "" {
		dbPass = os.Getenv("POSTGRES_PASSWORD")
	}

	dbUrl := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", 
		dbUser, dbPass, dbHost, dbPort, dbName)

	log.Printf("Initializing schema migration...")
	// Point to the migration files inside the container
	var m *migrate.Migrate
	var err error
	maxRetries := 30

	for i := 0; i < maxRetries; i++ {
		m, err = migrate.New("file:///app/migrations", dbUrl)
		if err == nil {
			break
		}
		log.Printf("Migration initialization failed (attempt %d/%d): %v. Retrying in 2 seconds...", i+1, maxRetries, err)
		time.Sleep(2 * time.Second)
	}

	if err != nil {
		log.Printf("Migration initialization finally failed (might be in dev or path missing): %v", err)
		return
	}
	if err := m.Up(); err != nil && err != migrate.ErrNoChange {
		log.Fatal("Database migration failed:", err)
	}
	log.Println("Database schema is up to date.")
}

func main() {
	initSchema()
	models.InitDB()
	
	// --- Initialize Log Rotation ---
	logWriter := utils.NewDailyLogWriter("logs")
	// Output to both stdout and file
	multiWriter := io.MultiWriter(os.Stdout, logWriter)
	
	// Configure standard logger
	log.SetOutput(multiWriter)
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	
	// Configure Gin logger
	gin.DefaultWriter = multiWriter
	
	// Initialize Time Series Database (TDengine)
	db.InitTDengine()
	
	// Initialize Backup Service
	services.InitBackupService()

	// Initialize Alarm Service
	services.NewAlarmService()

	// Start Data Collector Service
	collector := services.NewCollectorService()
	collector.Start()
	// Note: collector.Stop() is not strictly needed as container kill handles cleanup,
	// but can be added if we implement graceful shutdown.

	r := gin.Default()

	// Setup Routes
	routes.SetupRoutes(r)

	// Health Check
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
			"system":  "EMS Backend",
		})
	})

	// API Group
	v1 := r.Group("/api/v1")
	{
		v1.GET("/info", func(c *gin.Context) {
			c.JSON(http.StatusOK, gin.H{
				"version": "1.0.0",
				"env":     os.Getenv("GIN_MODE"),
			})
		})
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	fmt.Printf("Server starting on port %s...\n", port)
	r.Run(":" + port)
}
