package server

import (
	"net/http"
	"os"
	"path/filepath"
	"strings"

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

type Options struct {
	UIServeDir   string
	BigscreenDir string
	TemplateDir  string
	StaticDir    string
	EnableCORS   bool
}

func NewRouter(opts Options) *gin.Engine {
	r := gin.New()
	r.Use(gin.Logger())
	r.Use(gin.Recovery())

	if opts.EnableCORS {
		r.Use(func(c *gin.Context) {
			c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
			c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
			if c.Request.Method == http.MethodOptions {
				c.AbortWithStatus(http.StatusNoContent)
				return
			}
			c.Next()
		})
	}

	if strings.TrimSpace(opts.StaticDir) != "" {
		r.Static("/static", opts.StaticDir)
	}
	// Do not render legacy templates; keep core frontend under /ui

	api := r.Group("/api")
	{
		api.GET("/health", handleHealth)
		api.GET("/system/status", handleSystemStatus)
		api.GET("/stations", handleStations)
		api.GET("/data", handleData)
		api.GET("/forecast", handleForecast)
		api.GET("/radar/times", handleRadarTimes)
		api.GET("/radar/tiles_at", handleRadarTilesAt)
		api.GET("/rain/times", handleRainTimes)
		api.GET("/rain/tiles_at", handleRainTilesAt)
	}

	hasUI := strings.TrimSpace(opts.UIServeDir) != ""
	if hasUI {
		// Serve built Angular assets under /ui for static files
		r.Static("/ui", opts.UIServeDir)
		// Serve Angular index.html at root
		r.GET("/", func(c *gin.Context) {
			c.File(filepath.Join(opts.UIServeDir, "index.html"))
		})
	}

	hasBigscreen := strings.TrimSpace(opts.BigscreenDir) != ""
	var bigscreenIndex string
	if hasBigscreen {
		bigscreenDir := filepath.Clean(opts.BigscreenDir)
		bigscreenIndex = filepath.Join(bigscreenDir, "index.html")
		serveBigscreenIndex := func(c *gin.Context) {
			c.File(bigscreenIndex)
		}
		r.GET("/bigscreen", serveBigscreenIndex)
		r.GET("/bigscreen/*filepath", func(c *gin.Context) {
			rel := strings.TrimPrefix(c.Param("filepath"), "/")
			if rel == "" {
				serveBigscreenIndex(c)
				return
			}
			full := filepath.Join(bigscreenDir, filepath.FromSlash(rel))
			if !strings.HasPrefix(full, bigscreenDir+string(os.PathSeparator)) && full != bigscreenDir {
				c.AbortWithStatus(http.StatusBadRequest)
				return
			}
			if info, err := os.Stat(full); err == nil && !info.IsDir() {
				c.File(full)
				return
			}
			serveBigscreenIndex(c)
		})
	}

	// Optional SPA fallback: serve index.html for non-API, non-static routes
	r.NoRoute(func(c *gin.Context) {
		p := c.Request.URL.Path
		if strings.HasPrefix(p, "/api/") || strings.HasPrefix(p, "/static/") {
			c.AbortWithStatus(http.StatusNotFound)
			return
		}
		if hasBigscreen && strings.HasPrefix(p, "/bigscreen") {
			c.File(bigscreenIndex)
			return
		}
		if hasUI {
			c.File(filepath.Join(opts.UIServeDir, "index.html"))
			return
		}
		c.AbortWithStatus(http.StatusNotFound)
	})

	return r
}
