// Package server provides the http server for schreifuchs.ch.
package server

import (
	"context"
	"fmt"
	"log/slog"
	"net/http"
	"os"
	"strconv"
	"time"

	"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/pkg/config"
)

type Server struct {
	port int
	cfg  config.Cfg
}

// Start starts a new http server. When the context gets canceled, the server stops gracefully.
func Start(ctx context.Context, cfg config.Cfg) (err error) {
	port, _ := strconv.Atoi(os.Getenv("PORT"))
	if port == 0 {
		port = 8080
	}
	s := &Server{
		port: port,
		cfg:  cfg,
	}

	hander, err := s.allRoutes()
	if err != nil {
		err = fmt.Errorf("could not setup routes: %w", err)
		return
	}

	// Declare Server config
	srv := &http.Server{
		Addr:         fmt.Sprintf(":%d", s.port),
		Handler:      hander,
		IdleTimeout:  time.Minute,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 30 * time.Second,
	}
	idleConnsClosed := make(chan struct{})

	go func() {
		<-ctx.Done()

		slog.Info("shutting down server")

		// Shutdown server when ctx done
		if err = srv.Shutdown(context.Background()); err != nil {
			// Error from closing listeners, or context timeout:
			err = fmt.Errorf("error while shutting down server: %w", err)
		}

		close(idleConnsClosed)
	}()

	slog.Info("starting server", "address", srv.Addr)
	if err := srv.ListenAndServe(); err != http.ErrServerClosed {
		return fmt.Errorf("error while serving: %w", err)
	}

	<-idleConnsClosed
	return err
}
