package serverimp

import (
	"context"
	"errors"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tech/sendico/pkg/api/routers"
	"github.com/tech/sendico/pkg/api/routers/health"
	"go.uber.org/zap"
)

func (i *Imp) startMetrics(cfg *metricsConfig) {
	if i == nil {
		return
	}
	address := ""
	if cfg != nil {
		address = strings.TrimSpace(cfg.Address)
	}
	if address == "" {
		i.logger.Info("Metrics endpoint disabled")
		return
	}

	listener, err := net.Listen("tcp", address)
	if err != nil {
		i.logger.Error("Failed to bind metrics listener", zap.String("address", address), zap.Error(err))
		return
	}

	router := chi.NewRouter()
	router.Handle("/metrics", promhttp.Handler())

	var healthRouter routers.Health
	if hr, err := routers.NewHealthRouter(i.logger.Named("metrics"), router, ""); err != nil {
		i.logger.Warn("Failed to initialise health router", zap.Error(err))
	} else {
		hr.SetStatus(health.SSStarting)
		healthRouter = hr
	}

	i.metricsHealth = healthRouter
	i.metricsSrv = &http.Server{
		Addr:              address,
		Handler:           router,
		ReadHeaderTimeout: 5 * time.Second,
	}

	if healthRouter != nil {
		healthRouter.SetStatus(health.SSRunning)
	}

	go func() {
		i.logger.Info("Prometheus endpoint listening", zap.String("address", address))
		if err := i.metricsSrv.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
			i.logger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(err))
			if healthRouter != nil {
				healthRouter.SetStatus(health.SSTerminating)
			}
		}
	}()
}

func (i *Imp) shutdownMetrics(ctx context.Context) {
	if i.metricsHealth != nil {
		i.metricsHealth.SetStatus(health.SSTerminating)
		i.metricsHealth.Finish()
		i.metricsHealth = nil
	}
	if i.metricsSrv == nil {
		return
	}
	if err := i.metricsSrv.Shutdown(ctx); err != nil && !errors.Is(err, http.ErrServerClosed) {
		i.logger.Warn("Failed to stop metrics server", zap.Error(err))
	} else {
		i.logger.Info("Metrics server stopped")
	}
	i.metricsSrv = nil
}
