package server

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

	"github.com/gin-gonic/gin"

	"github.com/user-management-system/internal/api/handler"
	"github.com/user-management-system/internal/api/middleware"
	"github.com/user-management-system/internal/api/router"
	"github.com/user-management-system/internal/auth"
	"github.com/user-management-system/internal/cache"
	"github.com/user-management-system/internal/config"
	"github.com/user-management-system/internal/database"
	"github.com/user-management-system/internal/monitoring"
	"github.com/user-management-system/internal/repository"
	"github.com/user-management-system/internal/security"
	"github.com/user-management-system/internal/service"
)

func Serve(cfg *config.Config) error {
	// 设置 Gin 模式
	gin.SetMode(resolveGinMode(cfg.Server.Mode))

	// 初始化数据库
	db, err := database.NewDB(cfg)
	if err != nil {
		return fmt.Errorf("connect database failed: %w", err)
	}

	// 执行数据库迁移
	if err := db.AutoMigrate(cfg); err != nil {
		return fmt.Errorf("auto migrate failed: %w", err)
	}

	// P1-3：Argon2id 启动时自适应校准
	auth.CalibrateArgon2id(500 * time.Millisecond)

	// 初始化 JWT 管理器
	jwtManager, err := auth.NewJWTWithOptions(auth.JWTOptions{
		HS256Secret:        cfg.JWT.Secret,
		AccessTokenExpire:  cfg.JWT.AccessTokenTTL(),
		RefreshTokenExpire: cfg.JWT.RefreshTokenTTL(),
	})
	if err != nil {
		return fmt.Errorf("create jwt manager failed: %w", err)
	}

	// 初始化缓存
	l1Cache := cache.NewL1Cache()
	redisAddr := fmt.Sprintf("%s:%d", cfg.Redis.Host, cfg.Redis.Port)
	redisEnabled := cfg.Redis.Host != "" && cache.ProbeRedis(redisAddr, cfg.Redis.Password, cfg.Redis.DB)
	if !redisEnabled {
		log.Printf("cache: running in memory-only mode (Redis unreachable or not configured)")
	}
	l2Cache := cache.NewRedisCacheWithConfig(cache.RedisCacheConfig{
		Enabled:  redisEnabled,
		Addr:     redisAddr,
		Password: cfg.Redis.Password,
		DB:       cfg.Redis.DB,
	})
	defer l2Cache.Close()
	cacheManager := cache.NewCacheManager(l1Cache, l2Cache)

	// 初始化 Repository
	userRepo := repository.NewUserRepository(db.DB)
	roleRepo := repository.NewRoleRepository(db.DB)
	permissionRepo := repository.NewPermissionRepository(db.DB)
	userRoleRepo := repository.NewUserRoleRepository(db.DB)
	rolePermissionRepo := repository.NewRolePermissionRepository(db.DB)
	deviceRepo := repository.NewDeviceRepository(db.DB)
	loginLogRepo := repository.NewLoginLogRepository(db.DB)
	operationLogRepo := repository.NewOperationLogRepository(db.DB)
	customFieldRepo := repository.NewCustomFieldRepository(db.DB)
	userCustomFieldValueRepo := repository.NewUserCustomFieldValueRepository(db.DB)
	themeRepo := repository.NewThemeConfigRepository(db.DB)
	socialRepo, err := repository.NewSocialAccountRepository(db.DB)
	if err != nil {
		return fmt.Errorf("initialize social account repository failed: %w", err)
	}
	passwordHistoryRepo := repository.NewPasswordHistoryRepository(db.DB)

	// 初始化 Service
	deviceService := service.NewDeviceService(deviceRepo, userRepo)
	authService := service.NewAuthService(
		userRepo,
		socialRepo,
		jwtManager,
		cacheManager,
		8,              // passwordMinLength
		5,              // maxLoginAttempts
		15*time.Minute, // loginLockDuration
	)
	authService.SetRoleRepositories(userRoleRepo, roleRepo)
	authService.SetLoginLogRepository(loginLogRepo)
	authService.SetDeviceService(deviceService)

	// IP 过滤中间件
	var ipFilterMiddleware *middleware.IPFilterMiddleware
	ipFilter := security.NewIPFilter()
	if ipFilter != nil {
		ipFilterMiddleware = middleware.NewIPFilterMiddleware(ipFilter, middleware.IPFilterConfig{
			TrustProxy: cfg.CORS.AllowCredentials,
		})
	}

	// 初始化异常检测器并注入
	anomalyDetector := security.NewAnomalyDetector(security.DefaultAnomalyConfig, ipFilter)
	authService.SetAnomalyDetector(anomalyDetector)
	log.Println("anomaly detector initialized")

	userService := service.NewUserService(userRepo, userRoleRepo, roleRepo, passwordHistoryRepo)
	roleService := service.NewRoleService(roleRepo, rolePermissionRepo)
	permissionService := service.NewPermissionService(permissionRepo)
	loginLogService := service.NewLoginLogService(loginLogRepo)
	operationLogService := service.NewOperationLogService(operationLogRepo)
	captchaService := service.NewCaptchaService(cacheManager)
	totpService := service.NewTOTPService(userRepo)

	passwordResetConfig := service.DefaultPasswordResetConfig()
	passwordResetService := service.NewPasswordResetService(userRepo, cacheManager, passwordResetConfig).
		WithPasswordHistoryRepo(passwordHistoryRepo)

	webhookService := service.NewWebhookService(db.DB, service.WebhookServiceConfig{
		Enabled: false,
	})
	exportService := service.NewExportService(userRepo, roleRepo)
	statsService := service.NewStatsService(userRepo, loginLogRepo)
	customFieldService := service.NewCustomFieldService(customFieldRepo, userCustomFieldValueRepo)
	themeService := service.NewThemeService(themeRepo)

	// 设置 CORS 配置
	if err := middleware.SetCORSConfig(cfg.CORS); err != nil {
		return fmt.Errorf("invalid cors config: %w", err)
	}

	// 初始化中间件
	rateLimitMiddleware := middleware.NewRateLimitMiddleware(cfg.RateLimit)
	authMiddleware := middleware.NewAuthMiddleware(
		jwtManager,
		userRepo,
		userRoleRepo,
		l1Cache,
	)
	authMiddleware.SetCacheManager(cacheManager)

	opLogMiddleware := middleware.NewOperationLogMiddleware(operationLogRepo)

	// 初始化 Handler
	authHandler := handler.NewAuthHandler(authService)
	userHandler := handler.NewUserHandler(userService)
	roleHandler := handler.NewRoleHandler(roleService)
	permissionHandler := handler.NewPermissionHandler(permissionService)
	deviceHandler := handler.NewDeviceHandler(deviceService)
	logHandler := handler.NewLogHandler(loginLogService, operationLogService)
	captchaHandler := handler.NewCaptchaHandler(captchaService)
	totpHandler := handler.NewTOTPHandler(authService, totpService)
	webhookHandler := handler.NewWebhookHandler(webhookService)
	exportHandler := handler.NewExportHandler(exportService)
	statsHandler := handler.NewStatsHandler(statsService)
	passwordResetHandler := handler.NewPasswordResetHandler(passwordResetService)
	smsHandler := handler.NewSMSHandler(authService, nil)
	avatarHandler := handler.NewAvatarHandler(userRepo)
	customFieldHandler := handler.NewCustomFieldHandler(customFieldService)
	themeHandler := handler.NewThemeHandler(themeService)

	// 初始化 SSO 管理器
	ssoManager := auth.NewSSOManager()
	ssoClientsStore := auth.NewDefaultSSOClientsStore()
	ssoHandler := handler.NewSSOHandler(ssoManager, ssoClientsStore)

	// 系统设置服务
	settingsService := service.NewSettingsService()
	settingsHandler := handler.NewSettingsHandler(settingsService)

	// SSO 会话清理 context（随服务器关闭而取消）
	ssoCtx, ssoCancel := context.WithCancel(context.Background())
	defer ssoCancel()
	ssoManager.StartCleanup(ssoCtx)

	// 初始化监控指标
	metrics := monitoring.GetGlobalMetrics()
	sloMetrics := monitoring.GetGlobalSLOMetrics()

	// 启动后台 goroutine 定期采集系统指标
	metricsCtx, metricsCancel := context.WithCancel(context.Background())
	defer metricsCancel()
	go monitoring.StartSystemMetricsCollector(metricsCtx, metrics, sloMetrics, db.DB)

	// 设置路由
	r := router.NewRouter(
		authHandler, userHandler, roleHandler, permissionHandler, deviceHandler,
		logHandler, authMiddleware, rateLimitMiddleware, opLogMiddleware,
		passwordResetHandler, captchaHandler, totpHandler, webhookHandler,
		ipFilterMiddleware, exportHandler, statsHandler, smsHandler, customFieldHandler, themeHandler, ssoHandler,
		settingsHandler, metrics, avatarHandler,
	)
	engine := r.Setup()

	// 健康检查
	healthCheck := monitoring.NewHealthCheck(db.DB)
	engine.GET("/health", healthCheck.Handler)
	engine.GET("/health/live", healthCheck.LivenessHandler)
	engine.GET("/health/ready", healthCheck.ReadinessHandler)

	// 启动服务器
	addr := fmt.Sprintf(":%d", cfg.Server.Port)
	srv := &http.Server{
		Addr:         addr,
		Handler:      engine,
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	go func() {
		log.Printf("server listening on %s", addr)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen failed: %v", err)
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("shutting down server...")

	// 关闭 Webhook 服务
	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer shutdownCancel()
	if err := webhookService.Shutdown(shutdownCtx); err != nil {
		log.Printf("webhook service shutdown: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		return fmt.Errorf("server forced to shutdown: %w", err)
	}

	log.Println("server exited")
	return nil
}

func resolveGinMode(mode string) string {
	switch mode {
	case "debug":
		return gin.DebugMode
	case "test":
		return gin.TestMode
	default:
		return gin.ReleaseMode
	}
}
