package server

import (
	"NetworkAuth/utils"
	"io"
	"io/fs"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"path/filepath"
	"strings"

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

var frontendFS fs.FS

func SetFrontendFS(fsys fs.FS) {
	frontendFS = fsys
}

// RegisterRoutes 聚合注册所有路由
func RegisterRoutes(r *gin.Engine) {
	// 1. 所有接口路由基于 /api
	apiGroup := r.Group("/api")
	RegisterInstallRoutes(apiGroup)
	RegisterDefaultRoutes(apiGroup)
	RegisterAdminRoutes(apiGroup)

	// 2. 注册前端静态资源及兜底路由
	registerFrontendRoutes(r)
}

// registerFrontendRoutes 注册前端静态资源及兜底路由
func registerFrontendRoutes(r *gin.Engine) {
	distConfig := viper.GetString("server.dist")
	var fileServer http.Handler

	// 判断是否配置了外部 dist (支持 http 反向代理或本地目录)
	if distConfig != "" {
		if strings.HasPrefix(distConfig, "http://") || strings.HasPrefix(distConfig, "https://") {
			// 反向代理到前端开发服务器
			r.Use(func(c *gin.Context) {
				if !strings.HasPrefix(c.Request.URL.Path, "/api") {
					proxy := httputil.NewSingleHostReverseProxy(&url.URL{
						Scheme: strings.Split(distConfig, "://")[0],
						Host:   strings.TrimPrefix(distConfig, strings.Split(distConfig, "://")[0]+"://"),
					})
					proxy.ServeHTTP(c.Writer, c.Request)
					c.Abort()
				}
			})
			return // 反向代理接管了所有非 API 路由，直接返回
		} else {
			// 使用本地外部目录
			if !filepath.IsAbs(distConfig) {
				distConfig = filepath.Join(utils.GetRootDir(), distConfig)
			}
			fileServer = http.FileServer(http.Dir(distConfig))

			// 拦截并处理静态资源请求
			r.Use(func(c *gin.Context) {
				path := c.Request.URL.Path
				if strings.HasPrefix(path, "/api") {
					c.Next()
					return
				}

				cleanPath := strings.TrimPrefix(path, "/")
				if cleanPath == "" {
					cleanPath = "index.html"
				}

				fullPath := distConfig + "/" + cleanPath
				if stat, err := os.Stat(fullPath); err == nil && !stat.IsDir() {
					if strings.HasPrefix(path, "/static/") || strings.HasPrefix(path, "/assets/") {
						c.Header("Cache-Control", "public, max-age=31536000")
					}
					fileServer.ServeHTTP(c.Writer, c.Request)
					c.Abort()
					return
				}
				c.Next()
			})

			// SPA 前端路由兜底
			r.NoRoute(func(c *gin.Context) {
				if strings.HasPrefix(c.Request.URL.Path, "/api") {
					c.JSON(http.StatusNotFound, gin.H{"code": 404, "msg": "API Not Found"})
					return
				}
				c.Header("Content-Type", "text/html; charset=utf-8")
				c.File(distConfig + "/index.html")
			})
			return
		}
	}

	if frontendFS == nil {
		panic("Failed to initialize embedded static files: frontend fs is nil")
	}

	// 提供静态文件服务器
	fileServer = http.FileServer(http.FS(frontendFS))

	// 拦截并处理静态资源请求
	r.Use(func(c *gin.Context) {
		path := c.Request.URL.Path
		// 如果是 API 请求，直接放行
		if strings.HasPrefix(path, "/api") {
			c.Next()
			return
		}

		// 检查静态文件中是否存在该路径
		// 移除开头的 "/"
		cleanPath := strings.TrimPrefix(path, "/")
		if cleanPath == "" {
			cleanPath = "index.html"
		}

		// 尝试在嵌入的文件系统中查找文件
		if _, err := fs.Stat(frontendFS, cleanPath); err == nil {
			// 文件存在，交由 FileServer 处理
			// 设置一些常见的缓存头
			if strings.HasPrefix(path, "/static/") || strings.HasPrefix(path, "/assets/") {
				c.Header("Cache-Control", "public, max-age=31536000")
			}
			fileServer.ServeHTTP(c.Writer, c.Request)
			c.Abort()
			return
		}

		c.Next()
	})

	// SPA 前端路由兜底 (处理 History 模式)
	r.NoRoute(func(c *gin.Context) {
		// 如果是 API 请求找不到路由，返回 404 JSON
		if strings.HasPrefix(c.Request.URL.Path, "/api") {
			c.JSON(http.StatusNotFound, gin.H{
				"code": 404,
				"msg":  "API Not Found",
			})
			return
		}

		// 其他所有非 API 请求，都返回 index.html 交给前端 Vue Router 处理
		c.Header("Content-Type", "text/html; charset=utf-8")
		indexFile, err := frontendFS.Open("index.html")
		if err != nil {
			c.String(http.StatusInternalServerError, "Failed to load index.html")
			return
		}
		defer indexFile.Close()

		stat, _ := indexFile.Stat()
		http.ServeContent(c.Writer, c.Request, "index.html", stat.ModTime(), indexFile.(io.ReadSeeker))
	})
}
