package main

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

	"github.com/gorilla/sessions"
	"github.com/joho/godotenv"
	_ "github.com/lib/pq"

	"github.com/forgeo/forgebucket/internal/api"
	"github.com/forgeo/forgebucket/internal/config"
	"github.com/forgeo/forgebucket/internal/db"
	gitdomain "github.com/forgeo/forgebucket/internal/domain/git"
	"github.com/forgeo/forgebucket/internal/models/migrations"
	"github.com/forgeo/forgebucket/web"
)

func main() {
	_ = godotenv.Load()

	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("config: %v", err)
	}

	engine, err := db.Open(cfg.DatabaseURL, cfg.Debug)
	if err != nil {
		log.Fatalf("database: %v", err)
	}
	defer engine.Close()

	if err := migrations.Run(engine); err != nil {
		log.Fatalf("migrations: %v", err)
	}

	gitdomain.SetRepoRoot(cfg.RepoRoot)

	store := sessions.NewCookieStore([]byte(cfg.SessionSecret))
	store.Options = &sessions.Options{
		Path:     "/",
		MaxAge:   86400 * 7,
		HttpOnly: true,
		Secure:   !cfg.Debug,
		SameSite: http.SameSiteLaxMode,
	}

	handler := api.New(cfg, engine, store, web.FS())

	srv := &http.Server{
		Addr:         fmt.Sprintf(":%s", cfg.Port),
		Handler:      handler,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 60 * time.Second,
		IdleTimeout:  120 * time.Second,
	}

	go func() {
		log.Printf("ForgeBucket listening on http://localhost:%s", cfg.Port)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("server: %v", err)
		}
	}()

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

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Printf("shutdown: %v", err)
	}
	log.Println("ForgeBucket stopped")
}
