package main

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

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"vul-backend/internal/config"
	"vul-backend/internal/infra/mysql"
	"vul-backend/internal/middleware"
	vulnhandler "vul-backend/internal/modules/vuln/handler"
	vulnrepository "vul-backend/internal/modules/vuln/repository"
	vulnservice "vul-backend/internal/modules/vuln/service"
	"vul-backend/internal/pkg/logger"
)

func main() {
	var configPath string
	flag.StringVar(&configPath, "config", "./configs/config.yaml", "配置文件路径")
	flag.Parse()

	// 加载配置
	cfg, err := config.Load(configPath)
	if err != nil {
		log.Fatalf("加载配置失败: %v", err)
	}

	// 初始化日志
	appLogger := logger.New(cfg.Log)
	defer func() { _ = appLogger.Sync() }()

	appLogger.Info("启动漏洞管理 API 服务",
		"env", cfg.App.Environment,
		"port", cfg.HTTP.Port,
	)

	// 连接数据库
	db, err := mysql.New(cfg.Database)
	if err != nil {
		appLogger.Error("数据库连接失败", "error", err)
		os.Exit(1)
	}

	// 自动迁移
	if err := mysql.AutoMigrate(db); err != nil {
		appLogger.Warn("数据库迁移失败", "error", err)
	}

	// 初始化服务
	engine := setupRouter(cfg, appLogger, db)

	// 启动服务器
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	srv := &http.Server{
		Addr:         fmt.Sprintf("%s:%d", cfg.HTTP.Host, cfg.HTTP.Port),
		Handler:      engine,
		ReadTimeout:  cfg.HTTP.ReadTimeout,
		WriteTimeout: cfg.HTTP.WriteTimeout,
	}

	go func() {
		appLogger.Info("HTTP 服务器监听中", "addr", srv.Addr)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			appLogger.Error("服务器启动失败", "error", err)
			stop()
		}
	}()

	<-ctx.Done()
	appLogger.Info("接收到关闭信号，开始优雅关闭")

	shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := srv.Shutdown(shutdownCtx); err != nil {
		appLogger.Error("优雅关闭失败", "error", err)
		os.Exit(1)
	}

	appLogger.Info("漏洞管理 API 服务已停止")
}

func setupRouter(cfg *config.Config, log *logger.Logger, db *gorm.DB) *gin.Engine {
	if cfg.App.Environment == "production" {
		gin.SetMode(gin.ReleaseMode)
	}

	engine := gin.New()
	engine.Use(
		middleware.Recovery(log),
		middleware.RequestLogger(log),
		middleware.CORS(cfg.HTTP),
	)

	// 初始化仓储层
	vulnRepo := vulnrepository.NewVulnerabilityRepository(db)
	tagRepo := vulnrepository.NewTagRepository(db)
	channelRepo := vulnrepository.NewDiscoveryChannelRepository(db)

	// 初始化服务层
	vulnSvc := vulnservice.New(vulnRepo, channelRepo)
	tagSvc := vulnservice.NewTagService(tagRepo)
	channelSvc := vulnservice.NewDiscoveryChannelService(channelRepo)

	// 初始化处理器
	vulnHandler := vulnhandler.New(vulnSvc)
	tagHandler := vulnhandler.NewTagHandler(tagSvc)
	channelHandler := vulnhandler.NewDiscoveryChannelHandler(channelSvc)

	// 注册路由
	api := engine.Group("/api/v1")
	{
		vulnGroup := api.Group("/vulnerabilities")
		vulnHandler.RegisterRoutes(vulnGroup)

		tagGroup := api.Group("/vulnerability-tags")
		tagHandler.RegisterRoutes(tagGroup, tagGroup)

		channelGroup := api.Group("/vulnerability-discovery-channels")
		channelHandler.RegisterRoutes(channelGroup, channelGroup)
	}

	// 健康检查
	engine.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"status": "ok",
			"service": "vul-backend",
		})
	})

	// 版本信息
	engine.GET("/version", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"version": cfg.App.Version,
			"name": cfg.App.Name,
		})
	})

	return engine
}
