package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"producer/internal/api"
	"producer/internal/database"
	"producer/internal/kafka"
	"producer/internal/logging"
	"producer/pkg/utils"
	"syscall"
	"time"

	"github.com/joho/godotenv"
)

func main() {
	// Print current working directory for debugging
	cwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("Error getting current working directory: %v", err)
	}
	log.Printf("Current working directory: %s", cwd)

	// Cargar variables de entorno desde archivo .env
	envErr := godotenv.Load()
	if envErr != nil {
		log.Printf("Warning: No se pudo cargar el archivo .env: %v", envErr)
		log.Println("Continuando con variables de entorno del sistema o valores predeterminados")

		// Try loading from explicit path
		alternativePaths := []string{
			"./.env",
			"../.env",
			"../../.env",
			"../main/.env",
		}

		for _, path := range alternativePaths {
			log.Printf("Trying to load .env from: %s", path)
			if err := godotenv.Load(path); err == nil {
				log.Printf("Successfully loaded .env from: %s", path)
				break
			}
		}
	} else {
		log.Println("Archivo .env cargado correctamente")
	}

	// Configurar sistema de logs
	logConfig := &logging.LogConfig{
		BaseDir:      utils.GetEnv("LOG_DIR", "./logs"),
		BaseFilename: utils.GetEnv("LOG_FILENAME", "producer.log"),
		MaxSize:      utils.GetEnvInt("LOG_MAX_SIZE", 1),
		MaxBackups:   utils.GetEnvInt("LOG_MAX_BACKUPS", 5),
		MaxAge:       utils.GetEnvInt("LOG_MAX_AGE", 30),
		Compress:     utils.GetEnvBool("LOG_COMPRESS", true),
	}

	logSystem, err := logging.NewLoggerSystem(logConfig)
	if err != nil {
		log.Fatalf("Error iniciando sistema de logs: %v", err)
	}
	defer logSystem.Close()

	// Configurar los loggers globales
	logging.InfoLogger = logSystem.InfoLogger
	logging.ErrorLogger = logSystem.ErrorLogger

	logging.InfoLogger.Println("Iniciando servidor...")

	// Print some environment variables to verify they're loaded
	log.Printf("DB_HOST: %s", utils.GetEnv("DB_HOST", "not set"))
	log.Printf("KAFKA_BOOTSTRAP_SERVERS: %s", utils.GetEnv("KAFKA_BOOTSTRAP_SERVERS", "not set"))
	log.Printf("SERVER_PORT: %s", utils.GetEnv("SERVER_PORT", "not set"))

	// Database connection
	log.Println("Intentando conectar a la base de datos...")
	db, err := database.ConnectDB()
	if err != nil {
		log.Printf("Error conectando a la base de datos: %v", err)
		logging.ErrorLogger.Fatalf("Conexión BD falló: %v", err)
	}
	defer db.Close()
	logging.InfoLogger.Println("Conexión a base de datos establecida")

	// Kafka Client initialization
	log.Println("Inicializando cliente Kafka...")
	bootstrap := utils.GetEnv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
	log.Printf("Using Kafka bootstrap servers: %s", bootstrap)

	// Cliente único para todos los topics
	kc := kafka.NewKafkaClient(bootstrap)
	defer kc.Close()
	logging.InfoLogger.Println("Cliente Kafka inicializado")

	// API Server setup
	log.Println("Configurando servidor API...")
	server := api.NewAPIServer(kc, db)
	router := api.SetupRouter(server)

	// HTTP Server configuration
	addr := ":" + utils.GetEnv("SERVER_PORT", "8080")
	log.Printf("Configurando servidor HTTP en %s", addr)

	srv := &http.Server{
		Addr:         addr,
		Handler:      router,
		ReadTimeout:  utils.GetEnvDuration("SERVER_READ_TIMEOUT", 15*time.Second),
		WriteTimeout: utils.GetEnvDuration("SERVER_WRITE_TIMEOUT", 15*time.Second),
		IdleTimeout:  utils.GetEnvDuration("SERVER_IDLE_TIMEOUT", 60*time.Second),
	}

	// Canal para capturar errores del servidor
	serverErrors := make(chan error, 1)

	// Iniciar el servidor en una goroutine
	go func() {
		logging.InfoLogger.Printf("Servidor arrancando en %s", addr)
		serverErrors <- srv.ListenAndServe()
	}()

	// Canal para señales de sistema
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	// Esperar señal de término o error del servidor
	select {
	case err := <-serverErrors:
		if err != nil && err != http.ErrServerClosed {
			log.Printf("Error fatal del servidor: %v", err)
			logging.ErrorLogger.Fatalf("Error fatal del servidor: %v", err)
		}
	case sig := <-quit:
		logging.InfoLogger.Printf("Recibida señal de sistema: %v", sig)
		logging.InfoLogger.Println("Iniciando apagado graceful...")

		// Crear contexto con timeout para shutdown graceful
		ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
		defer cancel()

		// Intentar shutdown graceful
		if err := srv.Shutdown(ctx); err != nil {
			logging.ErrorLogger.Printf("Error durante shutdown: %v", err)
			// Si el shutdown falla, forzar cierre
			if err := srv.Close(); err != nil {
				logging.ErrorLogger.Printf("Error forzando cierre del servidor: %v", err)
			}
		}
	}

	logging.InfoLogger.Println("Servidor detenido correctamente")
}
