package main

import (
	"api-soap-facturacion/internal/api"
	"api-soap-facturacion/internal/config"
	"api-soap-facturacion/internal/database"
	"api-soap-facturacion/internal/logger"
	"api-soap-facturacion/internal/soap"
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	// Inicializar configuración
	cfg, err := config.LoadConfig()
	if err != nil {
		panic(fmt.Sprintf("Error al cargar la configuración: %v", err))
	}

	// Inicializar logger
	log := logger.NewLogger(cfg)
	//log.Info("Iniciando aplicación", logger.Field("app", cfg.App.Name))
	log.Info("Iniciando aplicación", logger.NewField("app", cfg.App.Name))

	// Conectar a la base de datos
	db, err := database.NewPostgresConnection(cfg.Database)
	if err != nil {
		//log.Fatal("Error al conectar a la base de datos", logger.Field("error", err))
		log.Fatal("Error al conectar a la base de datos", logger.NewField("error", err))
	}
	defer db.Close()

	// Verificar conexión a la base de datos
	if err := db.Ping(); err != nil {
		log.Error("Error al cargar parámetros desde la base de datos", logger.NewField("error", err))
	}
	log.Info("Conexión a la base de datos establecida")

	// Cargar parámetros desde la base de datos
	params, err := database.LoadParameters(db)
	if err != nil {
		log.Info("Parámetros cargados desde la base de datos", logger.NewField("count", len(params)))
	} else {
		log.Info("Parámetros cargados desde la base de datos", logger.NewField("count", len(params)))
		// Actualizar configuración con parámetros de la base de datos
		cfg.MergeParameters(params)
	}

	// Inicializar cliente SOAP
	soapClients := soap.NewSoapClients(cfg, log)

	// Inicializar API
	router := api.NewRouter(cfg, log, db, soapClients)

	// Configurar servidor HTTP
	srv := &http.Server{
		Addr:         fmt.Sprintf(":%d", cfg.App.Port),
		Handler:      router,
		ReadTimeout:  cfg.App.RequestTimeout * time.Second,
		WriteTimeout: cfg.App.RequestTimeout * time.Second,
		IdleTimeout:  120 * time.Second,
	}

	// Iniciar servidor en goroutine
	go func() {
		log.Info("Servidor iniciado", logger.NewField("port", cfg.App.Port))
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatal("Error al iniciar servidor", logger.NewField("error", err))
		}
	}()

	// Configurar captura de señales para graceful shutdown
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Info("Apagando servidor...")

	// Iniciar graceful shutdown
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Error al apagar servidor", logger.NewField("error", err))
	}
	log.Info("Servidor detenido correctamente")
}

//
//func main() {
//	// Inicializar configuración
//	cfg, err := config.LoadConfig()
//	if err != nil {
//		panic(fmt.Sprintf("Error al cargar la configuración: %v", err))
//	}
//
//	// Inicializar logger
//	log := logger.NewLogger(cfg)
//	//log.Info("Iniciando aplicación", logger.Field("app", cfg.App.Name))
//	log.Info("Iniciando aplicación", logger.NewField("app", cfg.App.Name))
//
//	// Conectar a la base de datos
//	db, err := database.NewPostgresConnection(cfg.Database)
//	if err != nil {
//		//log.Fatal("Error al conectar a la base de datos", logger.Field("error", err))
//		log.Fatal("Error al conectar a la base de datos", logger.NewField("error", err))
//	}
//	defer db.Close()
//
//	// Verificar conexión a la base de datos
//	if err := db.Ping(); err != nil {
//		log.Error("Error al cargar parámetros desde la base de datos", logger.NewField("error", err))
//	}
//	log.Info("Conexión a la base de datos establecida")
//
//	// Cargar parámetros desde la base de datos
//	params, err := database.LoadParameters(db)
//	if err != nil {
//		log.Info("Parámetros cargados desde la base de datos", logger.NewField("count", len(params)))
//	} else {
//		log.Info("Parámetros cargados desde la base de datos", logger.NewField("count", len(params)))
//		// Actualizar configuración con parámetros de la base de datos
//		cfg.MergeParameters(params)
//	}
//
//	// Inicializar cliente SOAP
//	soapClients := soap.NewSoapClients(cfg, log)
//
//	// Inicializar API
//	router := api.NewRouter(cfg, log, db, soapClients)
//
//	// Configurar servidor HTTP
//	srv := &http.Server{
//		Addr:         fmt.Sprintf(":%d", cfg.App.Port),
//		Handler:      router,
//		ReadTimeout:  cfg.App.RequestTimeout * time.Second,
//		WriteTimeout: cfg.App.RequestTimeout * time.Second,
//		IdleTimeout:  120 * time.Second,
//	}
//
//	// Iniciar servidor en goroutine
//	go func() {
//		log.Info("Servidor iniciado", logger.NewField("port", cfg.App.Port))
//		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
//			log.Fatal("Error al iniciar servidor", logger.NewField("error", err))
//		}
//	}()
//
//	// Configurar captura de señales para graceful shutdown
//	quit := make(chan os.Signal, 1)
//	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
//	<-quit
//	log.Info("Apagando servidor...")
//
//	// Iniciar graceful shutdown
//	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
//	defer cancel()
//	if err := srv.Shutdown(ctx); err != nil {
//		log.Fatal("Error al apagar servidor", logger.NewField("error", err))
//	}
//	log.Info("Servidor detenido correctamente")
//}
