// Filename: internal/app/app.go
package app

import (
	"context"
	"fmt"
	"gemini-balancer/internal/config"
	"gemini-balancer/internal/crypto"
	"gemini-balancer/internal/db/migrations"
	"gemini-balancer/internal/db/seeder"
	"gemini-balancer/internal/scheduler"
	"gemini-balancer/internal/service"
	"gemini-balancer/internal/settings"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

// App
type App struct {
	Config        *config.Config
	Router        *gin.Engine
	DB            *gorm.DB
	Logger        *logrus.Logger
	CryptoService *crypto.Service

	// 拥有独立生命周期的后台服务
	ResourceService    *service.ResourceService
	APIKeyService      *service.APIKeyService
	DBLogWriter        *service.DBLogWriterService
	AnalyticsService   *service.AnalyticsService
	HealthCheckService *service.HealthCheckService
	SettingsManager    *settings.SettingsManager
	GroupManager       *service.GroupManager
	TokenManager       *service.TokenManager
	Scheduler          *scheduler.Scheduler
}

// NewApp
func NewApp(
	cfg *config.Config,
	router *gin.Engine,
	db *gorm.DB,
	logger *logrus.Logger,
	cryptoService *crypto.Service,
	resourceService *service.ResourceService,
	apiKeyService *service.APIKeyService,
	dbLogWriter *service.DBLogWriterService,
	analyticsService *service.AnalyticsService,
	healthCheckService *service.HealthCheckService,
	settingsManager *settings.SettingsManager,
	groupManager *service.GroupManager,
	tokenManager *service.TokenManager,
	scheduler *scheduler.Scheduler,
) *App {
	return &App{
		Config:             cfg,
		Router:             router,
		DB:                 db,
		Logger:             logger,
		CryptoService:      cryptoService,
		ResourceService:    resourceService,
		APIKeyService:      apiKeyService,
		DBLogWriter:        dbLogWriter,
		AnalyticsService:   analyticsService,
		HealthCheckService: healthCheckService,
		SettingsManager:    settingsManager,
		GroupManager:       groupManager,
		TokenManager:       tokenManager,
		Scheduler:          scheduler,
	}
}

// Run 启动流程现在由App主动编排，而非被动接受
func (a *App) Run() error {
	// --- 阶段一: (数据库设置) ---
	a.Logger.Info("* [SYSTEM] * Preparing: Database Setup ...")

	// 步骤 1: (运行基础迁移，确保表存在)
	if err := migrations.RunMigrations(a.DB, a.Logger); err != nil {
		return fmt.Errorf("initial database migration failed: %w", err)
	}

	// 步骤 2: (运行所有版本化的数据迁移)
	if err := migrations.RunVersionedMigrations(a.DB, a.Config, a.Logger); err != nil {
		return fmt.Errorf("failed to run versioned migrations: %w", err)
	}

	// 步骤 3: (数据播种)
	seeder.RunSeeder(a.DB, a.CryptoService, a.Logger)
	a.Logger.Info("* [SYSTEM] * All Uitls READY. ---")

	// --- 阶段二: (启动后台服务) ---
	a.Logger.Info("* [SYSTEM] * Starting main: Background Services ")
	a.APIKeyService.Start()
	a.DBLogWriter.Start()
	a.AnalyticsService.Start()
	a.HealthCheckService.Start()
	a.Scheduler.Start()
	a.Logger.Info("* [SYSTEM] * All Background Services are RUNNING. ")

	// --- 阶段三: (优雅关机) ---
	defer a.Scheduler.Stop()
	defer a.HealthCheckService.Stop()
	defer a.AnalyticsService.Stop()
	defer a.APIKeyService.Stop()
	defer a.DBLogWriter.Stop()
	defer a.SettingsManager.Stop()
	defer a.TokenManager.Stop()

	// --- 阶段四: (HTTP服务器) ---
	serverAddr := fmt.Sprintf("0.0.0.0:%s", a.Config.Server.Port)
	srv := &http.Server{
		Addr:    serverAddr,
		Handler: a.Router,
	}
	go func() {
		a.Logger.Infof("* [SYSTEM] * HTTP Server Now Listening on %s ", serverAddr)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			a.Logger.Fatalf("HTTP server listen error: %s\n", err)
		}
	}()

	// --- 阶段五: (处理关机信号) ---
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	a.Logger.Info("* [SYSTEM] * Shutdown signal received. Executing strategic retreat...")
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		a.Logger.Fatal("Server forced to shutdown:", err)
	}
	a.Logger.Info("* [SYSTEM] * All units have ceased operations. Mission complete. ")
	return nil
}
