package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/gin-gonic/gin"

	"github.com/rycroftapparel/workpulse-api/internal/api"
	"github.com/rycroftapparel/workpulse-api/internal/config"
	appdb "github.com/rycroftapparel/workpulse-api/internal/db"
	"github.com/rycroftapparel/workpulse-api/internal/realtime"
)

func main() {
	if os.Getenv("GIN_MODE") == "release" {
		gin.SetMode(gin.ReleaseMode)
	}
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("config: %v", err)
	}
	db, err := appdb.Open(cfg)
	if err != nil {
		log.Fatalf("database: %v", err)
	}
	defer db.Close()

	if cfg.AutoMigrate {
		if err := appdb.RunMigrations(db); err != nil {
			log.Fatalf("migrate: %v", err)
		}
		log.Println("migrations applied (WORKPULSE_AUTO_MIGRATE=1)")
	}

	hub := realtime.NewHub()
	go hub.Run()

	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()
	shutdownRedis := realtime.StartRedisSubscriber(ctx, cfg, hub)
	defer shutdownRedis()

	srv := &api.Server{DB: db, Cfg: cfg, Hub: hub}
	r := api.Router(srv)

	httpSrv := &http.Server{
		Addr:              cfg.APIAddr,
		Handler:           r,
		ReadHeaderTimeout: cfg.HTTPReadHeaderTimeout,
		ReadTimeout:       cfg.HTTPReadTimeout,
		WriteTimeout:      cfg.HTTPWriteTimeout,
		IdleTimeout:       cfg.HTTPIdleTimeout,
	}

	log.Printf("WorkPulse API listening on http://%s (database=%q)", cfg.APIAddr, "workpulse")
	serverErrors := make(chan error, 1)
	go func() {
		serverErrors <- httpSrv.ListenAndServe()
	}()

	select {
	case err := <-serverErrors:
		if err != nil && err != http.ErrServerClosed {
			log.Fatalf("server: %v", err)
		}
	case <-ctx.Done():
		shutdownCtx, cancel := context.WithTimeout(context.Background(), cfg.HTTPShutdownTimeout)
		defer cancel()
		if err := httpSrv.Shutdown(shutdownCtx); err != nil {
			log.Printf("shutdown: %v", err)
		}
		err := <-serverErrors
		if err != nil && err != http.ErrServerClosed {
			log.Printf("server exit: %v", err)
		}
	}

	log.Printf("WorkPulse API stopped (was http://%s)", cfg.APIAddr)
}
