// cmd/consumer/main.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"consumer/internal/config"
	"consumer/internal/database"
	"consumer/internal/kafka"
	"consumer/internal/logging"
	"consumer/internal/notifier"
	"consumer/internal/soap"

	_ "github.com/lib/pq"
)

func main() {
	// Establecer señales para graceful shutdown
	ctx, cancel := context.WithCancel(context.Background())
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// Cargar configuración
	cfg, err := config.LoadConfig()
	if err != nil {
		log.Fatalf("Error cargando configuración: %v", err)
	}

	// Configurar logging
	logConfig := &logging.LogConfig{
		BaseDir:      cfg.LogDir,
		BaseFilename: cfg.LogFilename,
		MaxSize:      cfg.LogMaxSize,
		MaxBackups:   cfg.LogMaxBackups,
		MaxAge:       cfg.LogMaxAge,
		Compress:     cfg.LogCompress,
	}

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

	// Configuración de base de datos
	dsn := fmt.Sprintf(
		"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
		cfg.DBHost, cfg.DBUser, cfg.DBPassword, cfg.DBName, cfg.DBPort,
	)

	// Inicializar administrador de base de datos
	dbManager, err := database.NewDBManager(dsn, logSystem)
	if err != nil {
		logSystem.Error.Fatalf("Error conectando a la base de datos: %v", err)
	}
	defer dbManager.Close()

	// Configurar cliente SOAP
	soapClient := soap.NewSOAPClient(cfg.SoapServiceURL, logSystem)

	// Configurar notificador
	notifier := notifier.NewNotifier(
		cfg.SMTPHost,
		cfg.SMTPPort,
		cfg.SMTPUser,
		cfg.SMTPPass,
		logSystem,
	)

	// Inicializar consumidor Kafka
	consumer := kafka.NewKafkaConsumer(
		cfg.KafkaBrokers,
		cfg.KafkaConsumerGroupID,
		cfg.KafkaInputTopic,
		cfg.KafkaTopicEstado,
		cfg.KafkaTopicAnular,
		cfg.KafkaResultTopic,
		cfg.KafkaDLQTopic,
		dbManager,
		soapClient,
		notifier,
		logSystem,
	)
	defer consumer.Close()

	// Iniciar consumidor en goroutine
	go consumer.Run(ctx)

	// Esperar señal de apagado
	<-sigs
	logSystem.Info.Println("Señal de apagado recibida")
	cancel()

	// Esperar máximo 30 segundos para shutdown graceful
	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer shutdownCancel()

	// Esperar a que termine o timeout
	select {
	case <-time.After(25 * time.Second):
		logSystem.Info.Println("Tiempo de apagado casi agotado, forzando cierre...")
	case <-shutdownCtx.Done():
		logSystem.Info.Println("Contexto de apagado finalizado")
	}

	logSystem.Info.Println("Servicio finalizado")
}
