package app

import (
	"context"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

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

// Handler interface for services that need lifecycle management
type Handler interface {
	StartScheduler()
	StopScheduler()
}

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

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

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

	// Start background services
	a.startBackgroundServices()

	// 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
}

// startBackgroundServices starts all background services
func (a *App) startBackgroundServices() {
	log.Println("Starting background services...")

	// Start scheduler for auto-scanning
	go func() {
		a.handler.StartScheduler()
		log.Println("Scheduler started")
	}()

	// Note: Watch mode is started by the handlers package
	// after a 2-second delay, so we don't duplicate it here
}

// 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()

	// Channel to track shutdown completion
	done := make(chan struct{})

	// Perform shutdown in goroutine
	go func() {
		defer close(done)

		// Stop accepting new connections and shutdown HTTP server
		log.Println("Stopping HTTP server...")
		if err := a.echo.Close(); err != nil {
			log.Printf("Error stopping HTTP server: %v", err)
		}

		// Stop scheduler
		log.Println("Stopping scheduler...")
		a.handler.StopScheduler()

		log.Println("All services stopped")
	}()

	// Wait for shutdown or timeout
	select {
	case <-done:
		close(a.shutdownDone)
		log.Println("Graceful shutdown completed successfully")
		return nil
	case <-ctx.Done():
		close(a.shutdownDone)
		log.Printf("Shutdown timed out after %v", a.shutdownTimeout)
		return ctx.Err()
	}
}

// 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
}
