package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"

	"git.solsynth.dev/goatworks/turbine/pkg/shared/hash"
	"git.solsynth.dev/goatworks/turbine/pkg/shared/registrar"

	"github.com/gofiber/fiber/v3"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"github.com/spf13/viper"
)

func init() {
	log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
}

func main() {
	log.Info().Msg("Starting Config Service...")
	viper.SetConfigName("settings")
	viper.AddConfigPath(".")
	viper.SetConfigType("toml")

	if err := viper.ReadInConfig(); err != nil {
		log.Fatal().Err(err).Msg("Failed to read config file")
	}
	log.Info().Msg("Configuration loaded.")

	// --- Service Registration ---
	etcdEndpoints := viper.GetStringSlice("etcd.endpoints")
	if len(etcdEndpoints) == 0 {
		log.Fatal().Msg("etcd.endpoints not configured")
	}

	if viper.GetBool("etcd.insecure") {
		for i, ep := range etcdEndpoints {
			if !strings.HasPrefix(ep, "http://") && !strings.HasPrefix(ep, "https://") {
				etcdEndpoints[i] = "http://" + ep
			}
		}
	}

	serviceReg, err := registrar.NewServiceRegistrar(etcdEndpoints)
	if err != nil {
		log.Fatal().Err(err).Msg("Failed to create service registrar")
	}

	listenAddr := viper.GetString("listen")
	host := viper.GetString("host")
	if host == "" {
		log.Fatal().Msg("host not configured")
	}
	portStr := strings.TrimPrefix(listenAddr, ":")
	port, err := strconv.Atoi(portStr)
	if err != nil {
		log.Fatal().Err(err).Msg("Invalid listen address")
	}

	serviceName := "config"
	instanceID := fmt.Sprint(hash.Hash(fmt.Sprintf("%s-%s-%d", serviceName, host, port)))[:8]

	err = serviceReg.Register(serviceName, "http", instanceID, host, port, 30)
	if err != nil {
		log.Fatal().Err(err).Msg("Failed to register service")
	}
	log.Info().Str("service", serviceName).Str("instanceID", instanceID).Msg("Service registered successfully")

	// --- Web Server ---
	app := fiber.New(fiber.Config{
		ServerHeader: "Turbine Config",
	})

	// This is the main endpoint that serves the configuration as JSON.
	app.Get("/api/", func(c fiber.Ctx) error {
		log.Info().Msg("Serving shared configuration as JSON")

		// Use a new Viper instance to read the shared config
		v := viper.New()
		v.SetConfigName("shared_config")
		v.AddConfigPath(".") // Look in the current directory (pkg/config)
		v.SetConfigType("toml")

		if err := v.ReadInConfig(); err != nil {
			log.Error().Err(err).Msg("Failed to read shared_config.toml")
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"error": "could not load configuration",
			})
		}

		return c.JSON(v.AllSettings())
	})

	// Health check endpoint
	app.Get("/health", func(c fiber.Ctx) error {
		return c.SendString("Config service is running")
	})

	// --- Graceful Shutdown ---
	go func() {
		err := app.Listen(listenAddr, fiber.ListenConfig{DisableStartupMessage: true})
		if err != nil {
			log.Fatal().Err(err).Msg("Failed to start server")
		}
	}()
	log.Info().Msg("Server is listening on " + listenAddr)

	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
	<-stop

	log.Info().Msg("Shutting down service...")
	if err := serviceReg.Deregister(); err != nil {
		log.Error().Err(err).Msg("Failed to deregister service")
	} else {
		log.Info().Msg("Service deregistered successfully")
	}

	if err := app.Shutdown(); err != nil {
		log.Error().Err(err).Msg("Error during server shutdown")
	}
}
