package bootstrap

import (
	"context"
	"designs/app/common/request"
	"designs/app/common/response"
	"designs/config"
	"designs/global"
	"designs/route"
	"fmt"
	"go.uber.org/zap"
	"log"
	"net/http"
	"os"
	"os/signal"
	"runtime/debug"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
)

// 回收致命错误
func CustomRecovery(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {

			if v, ok := r.(request.ValidateError); ok {
				response.ParameterError(c, v)
				return
			}

			//打印错误堆栈信息
			errTitle := fmt.Sprintf("panic: %v", r)
			errMsg := fmt.Sprintf("stack: %v", string(debug.Stack()))

			global.App.Log.Error("custom_recovery", zap.Any("info", errTitle), zap.Stack("stack"))

			response.ServerError(c, errTitle+errMsg)
		}
	}()
	//继续后续接口调用
	c.Next()

}

func corsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 或者指定允许的源
		c.Writer.Header().Set("Access-Control-Max-Age", "86400")  // 缓存请求信息
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Length, Content-Type, Authorization, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Type")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}

func setupRouter() *gin.Engine {
	if config.Get("app.env") == "production" {
		gin.SetMode(gin.ReleaseMode)
	}
	router := gin.New()
	router.Use(gin.Logger(), CustomRecovery)
	router.Use(corsMiddleware())
	// 跨域处理
	//router.Use(middleware.Cors())

	// 前端项目静态资源
	// router.StaticFile("/", "./static/dist/index.html")
	// router.Static("/assets", "./static/dist/assets")
	// router.StaticFile("/favicon.ico", "./static/dist/favicon.ico")
	// 其他静态资源
	// router.Static("/public", "./static")
	// router.Static("/storage", "./storage/app/public")

	// 注册 api 分组路由
	apiGroup := router.Group("")
	route.SetApiGroupRoutes(apiGroup)

	return router
}

func RunServer() {
	r := setupRouter()

	srv := &http.Server{
		Addr:         ":" + config.Get("app.port"),
		ReadTimeout:  60 * time.Second,
		WriteTimeout: 60 * time.Second,
		Handler:      r,
	}
	fmt.Println("Starting server at port " + config.Get("app.port") + " ...")

	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()

	// 等待中断信号以优雅地关闭服务器（设置 5 秒的超时时间）
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("Shutdown Server ...")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")
}
