package main

import (
	"embed"
	"fmt"
	"io/fs"
	"log/slog"
	"net/http"
	"os"
	"time"

	"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/handlers"
	"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/middleware"
)

//go:embed web/static/*
var static embed.FS

func init() {
	_, jsonLogger := os.LookupEnv("JSON_LOGGER")
	_, debug := os.LookupEnv("DEBUG")

	var programLevel slog.Level
	if debug {
		programLevel = slog.LevelDebug
	}
	programLevel = slog.LevelDebug

	if jsonLogger {
		jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
			Level: programLevel,
		})
		slog.SetDefault(slog.New(jsonHandler))
	} else {
		textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
			Level: programLevel,
		})
		slog.SetDefault(slog.New(textHandler))
	}

	slog.Info("Logger initialized", slog.Bool("debug", debug))
}

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	addr := ":" + port

	mux := http.NewServeMux()

	// Use an embedded filesystem rooted at "web/static"
	fs, err := fs.Sub(static, "web/static")
	if err != nil {
		slog.Error("Failed to create sub filesystem", "error", err)
		return
	}
	// Serve files from the embedded /web/static directory at /static
	fileServer := http.FileServer(http.FS(fs))
	mux.Handle("GET /static/", http.StripPrefix("/static/", fileServer))

	mux.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		data, err := static.ReadFile("web/static/favicon.ico")
		if err != nil {
			http.NotFound(w, r)
			return
		}
		w.Header().Set("Content-Type", "text/plain")
		w.Write(data)
	})
	mux.HandleFunc("GET /robots.txt", func(w http.ResponseWriter, r *http.Request) {
		data, err := static.ReadFile("web/static/robots.txt")
		if err != nil {
			http.NotFound(w, r)
			return
		}
		w.Header().Set("Content-Type", "text/plain")
		w.Write(data)
	})

	mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte(`OK`))
	})

	mux.HandleFunc("GET /", handlers.RootHandler())

	chain := &middleware.Chain{}
	chain.Use(middleware.RecoverMiddleware)
	wrappedMux := chain.Then(mux)

	server := &http.Server{
		Addr:    fmt.Sprintf(":%s", port),
		Handler: wrappedMux,
		// Recommended timeouts from
		// https://blog.cloudflare.com/exposing-go-on-the-internet/
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  120 * time.Second,
	}

	slog.Info("Server listening", "addr", addr)

	if err := server.ListenAndServe(); err != nil {
		slog.Error("Server failed to start", "error", err)
	}
}
