package web

import (
	"fmt"
	"html/template"
	"net"
	"os"
	"strings"

	"speedtest/config"
	"speedtest/internal/store"
	"speedtest/internal/web/handlers"

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

// WebServer wraps the Gin engine and its dependencies.
type WebServer struct {
	engine *gin.Engine
	stores *store.Stores
	cfg    config.Config
}

// NewWebServer creates a new WebServer, initializes the Gin engine and registers routes.
func NewWebServer(cfg config.Config, stores *store.Stores) (*WebServer, error) {
	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.Use(gin.Logger())
	engine.Use(gin.Recovery())

	// 不信任默认代理（真实 IP 通过 X-Real-IP 头由 Caddy 注入，自行解析）
	_ = engine.SetTrustedProxies(nil)

	// 加载 HTML 模板
	tmpl := template.Must(template.New("").ParseGlob("internal/web/templates/*.html"))
	engine.SetHTMLTemplate(tmpl)

	handler, err := handlers.NewHandler(stores, cfg.Speedtest)
	if err != nil {
		return nil, err
	}

	ws := &WebServer{
		engine: engine,
		stores: stores,
		cfg:    cfg,
	}

	// 页面
	engine.GET("/", func(c *gin.Context) {
		c.HTML(200, "index.html", gin.H{})
	})

	// 测速 API
	api := engine.Group("/api")
	{
		api.GET("/ping", handler.Ping)
		api.GET("/download", handler.Download)
		api.POST("/upload", handler.Upload)
		api.POST("/result", handler.Result)
		api.GET("/rankings", handler.Rankings)
	}

	return ws, nil
}

// Start launches the HTTP server on the configured address.
// Supports both TCP (e.g. ":8080") and Unix socket (e.g. "/opt/speedtest/web.sock").
func (ws *WebServer) Start() error {
	addr := ws.cfg.Web.Addr

	// Unix socket：地址以 / 开头
	if strings.HasPrefix(addr, "/") {
		// 清理旧的 socket 文件
		os.Remove(addr)

		listener, err := net.Listen("unix", addr)
		if err != nil {
			return fmt.Errorf("监听 Unix socket 失败 %s: %w", addr, err)
		}
		// 允许 caddy 等外部进程连接
		os.Chmod(addr, 0666)

		return ws.engine.RunListener(listener)
	}

	// TCP 端口
	return ws.engine.Run(addr)
}
