package router

import (
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"

	"sproutworkcollect-backend/internal/config"
	"sproutworkcollect-backend/internal/handler"
	"sproutworkcollect-backend/internal/middleware"
	"sproutworkcollect-backend/internal/service"
)

// Setup creates and configures the Gin engine: middleware, services, handlers, and routes.
func Setup(cfg *config.Config) *gin.Engine {
	if !cfg.Debug {
		gin.SetMode(gin.ReleaseMode)
	}

	r := gin.Default()

	// Allow files up to 32 MB to stay in memory; larger ones spill to temp disk files.
	// This keeps RAM usage bounded even for gigabyte-scale uploads.
	r.MaxMultipartMemory = 32 << 20

	// 允许所有来源，并显式放开 Authorization 头，解决跨域访问后台接口时的预检失败问题。
	corsCfg := cors.Config{
		AllowOrigins: []string{"*"},
		AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders: []string{
			"Origin",
			"Content-Type",
			"Accept",
			"Authorization",
			"X-Requested-With",
		},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: false,
		MaxAge:           12 * time.Hour,
	}
	r.Use(cors.New(corsCfg))

	// ─── Services ─────────────────────────────────────────────────────────────
	workSvc := service.NewWorkService(cfg)
	settingsSvc := service.NewSettingsService(cfg)
	rateLimiter := service.NewRateLimiter()

	// ─── Handlers ─────────────────────────────────────────────────────────────
	pub := handler.NewPublicHandler(workSvc, settingsSvc, rateLimiter)
	media := handler.NewMediaHandler(workSvc, rateLimiter)
	admin := handler.NewAdminHandler(workSvc)

	// ─── Public routes ────────────────────────────────────────────────────────
	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"service":   "SproutWorkCollect API",
			"version":   "v1",
			"endpoints": []string{"/api/settings", "/api/works", "/api/works/{work_id}", "/api/search", "/api/categories", "/api/like/{work_id}"},
		})
	})

	api := r.Group("/api")
	{
		api.GET("/settings", pub.GetSettings)
		api.GET("/works", pub.GetWorks)
		api.GET("/works/:work_id", pub.GetWorkDetail)
		api.GET("/search", pub.SearchWorks)
		api.GET("/categories", pub.GetCategories)
		api.POST("/like/:work_id", pub.LikeWork)

		api.GET("/image/:work_id/:filename", media.ServeImage)
		api.GET("/video/:work_id/:filename", media.ServeVideo)
		api.GET("/download/:work_id/:platform/:filename", media.DownloadFile)
	}

	// ─── Admin routes (token-protected) ──────────────────────────────────────
	adm := api.Group("/admin", middleware.AdminAuth(cfg.AdminToken))
	{
		adm.GET("/works", admin.GetWorks)
		adm.POST("/works", admin.CreateWork)
		adm.PUT("/works/:work_id", admin.UpdateWork)
		adm.DELETE("/works/:work_id", admin.DeleteWork)
		adm.POST("/upload/:work_id/:file_type", admin.UploadFile)
		adm.DELETE("/delete-file/:work_id/:file_type/:filename", admin.DeleteFile)
	}

	return r
}
