package main

import (
	"database/sql"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	"git.ma-al.com/goc_marek/replica/pkg/replica"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// Initialize the logger
	replica.InitLogger()

	// Load configuration from environment
	cfg, err := replica.LoadEnvConfig()
	if err != nil {
		replica.Fatalf("Failed to load configuration: %v", err)
	}

	// Setup Graylog if enabled
	if cfg.Graylog.Enabled {
		replica.Infof("Graylog enabled: %s", cfg.Graylog.Endpoint)
		if err := replica.SetupGlobalGraylog(replica.GraylogConfig{
			Endpoint:    cfg.Graylog.Endpoint,
			Protocol:    cfg.Graylog.Protocol,
			Timeout:     cfg.Graylog.Timeout,
			Source:      cfg.Graylog.Source,
			ExtraFields: cfg.Graylog.ExtraFields,
		}); err != nil {
			replica.Warnf("Failed to setup Graylog: %v", err)
		} else {
			replica.Info("Graylog setup successful")
		}
	}

	replica.Infof("Loaded configuration: %d secondary(ies)", len(cfg.Secondaries))

	// Handle shutdown signals
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// Connect to primary MariaDB
	primaryDSN := cfg.Primary.User + ":" + cfg.Primary.Password + "@tcp(" + cfg.Primary.Host + ":" +
		strconv.FormatUint(uint64(cfg.Primary.Port), 10) + ")/?multiStatements=true"
	primaryDB, err := sql.Open("mysql", primaryDSN)
	if err != nil {
		replica.Fatalf("Failed to connect to primary MariaDB: %v", err)
	}
	defer primaryDB.Close()

	primaryDB.SetMaxOpenConns(25)
	primaryDB.SetMaxIdleConns(5)

	if err := primaryDB.Ping(); err != nil {
		replica.Fatalf("Failed to ping primary MariaDB: %v", err)
	}
	replica.Info("Connected to primary MariaDB")

	// Create multi-service manager
	multiService := replica.NewMultiBinlogSyncService()

	// Connect to each secondary and create services
	for _, secCfg := range cfg.Secondaries {
		replica.Infof("Connecting to secondary: %s (%s:%d)", secCfg.Name, secCfg.Host, secCfg.Port)

		secondaryDB, err := sql.Open("mysql", secCfg.DSN)
		if err != nil {
			replica.Fatalf("Failed to connect to secondary %s: %v", secCfg.Name, err)
		}
		defer secondaryDB.Close()

		secondaryDB.SetMaxOpenConns(25)
		secondaryDB.SetMaxIdleConns(5)

		if err := secondaryDB.Ping(); err != nil {
			replica.Fatalf("Failed to ping secondary %s: %v", secCfg.Name, err)
		}
		replica.Infof("Connected to secondary: %s", secCfg.Name)

		// Create service for this secondary
		service := replica.NewBinlogSyncService(cfg.Primary, primaryDB, secondaryDB, secCfg.Name)
		multiService.AddService(service)
	}

	// Start all services
	replica.Info("Starting binlog replication...")
	multiService.StartAll()

	// Wait for shutdown signal
	sig := <-sigChan
	replica.Infof("Received %v, shutting down...", sig)

	// Stop all services
	multiService.StopAll()
	replica.Info("Service stopped.")
}
