package app

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

	"github.com/labstack/echo/v5"
)

// App manages application lifecycle and graceful shutdown
type App struct {
	echo            *echo.Echo
	server          *http.Server
	shutdownTimeout time.Duration
	shutdownMutex   sync.Mutex
	shutdownDone    chan struct{}
}

// New creates a new App instance
func New(echo *echo.Echo) *App {
	return &App{
		echo:            echo,
		server:          nil,
		shutdownTimeout: 30 * time.Second,
		shutdownDone:    make(chan struct{}),
	}
}

func (a *App) StartServer(addr string) error {
	a.server = &http.Server{
		Addr:    addr,
		Handler: a.echo,
	}

	// Start HTTP server in background
	go func() {
		if err := a.server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
			log.Fatalf("Server failed to start: %v", err)
		}
	}()

	return nil
}

// Start begins all background services and blocks until shutdown signal
func (a *App) Start() error {
	log.Println("Starting application lifecycle management...")

	// Setup signal handling for graceful shutdown
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan,
		syscall.SIGINT,  // Ctrl+C
		syscall.SIGTERM, // kill
		syscall.SIGQUIT, // quit
	)

	// Wait for shutdown signal
	sig := <-sigChan
	log.Printf("Received signal: %v. Initiating graceful shutdown...", sig)

	// Perform graceful shutdown
	if err := a.Shutdown(); err != nil {
		log.Printf("Error during shutdown: %v", err)
		return err
	}

	log.Println("Application shutdown complete")
	return nil
}

// Shutdown performs graceful shutdown of all services
func (a *App) Shutdown() error {
	a.shutdownMutex.Lock()
	defer a.shutdownMutex.Unlock()

	select {
	case <-a.shutdownDone:
		log.Println("Shutdown already in progress")
		return nil
	default:
		// Continue with shutdown
	}

	log.Println("Beginning graceful shutdown...")

	// Create context with timeout
	ctx, cancel := context.WithTimeout(context.Background(), a.shutdownTimeout)
	defer cancel()
	log.Println("Stopping HTTP Server...")
	if a.server != nil {
		if err := a.server.Shutdown(ctx); err != nil {
			log.Printf("Error stopping HTTP server: %v", err)
		}
	}
	close(a.shutdownDone)
	log.Println("Graceful shutdown completed successfully")
	return nil
}

// SetShutdownTimeout sets the maximum time to wait for graceful shutdown
func (a *App) SetShutdownTimeout(timeout time.Duration) {
	a.shutdownTimeout = timeout
}

// ShutdownDone returns a channel that closes when shutdown is complete
func (a *App) ShutdownDone() <-chan struct{} {
	return a.shutdownDone
}
