package router

import (
	"bytes"
	"context"
	"log"
	"net/http"
	"strings"

	"bookhoard/internal/setupstatus"
	"bookhoard/templates"

	"github.com/labstack/echo/v5"
)

func isSetupComplete(cfg *Config) bool {
	getter := func(ctx context.Context) (string, error) {
		row, err := cfg.Queries.GetSystemConfig(ctx, "base_url")
		if err != nil {
			return "", err
		}
		return row.Value, nil
	}
	return setupstatus.IsSetupComplete(context.Background(), cfg.Queries, getter)
}

// setupAllowedAPIRoutes lists API endpoints that remain accessible before
// initial setup is complete so the server can be configured via API.
var setupAllowedAPIRoutes = []string{
	"/api/auth/register",
	"/api/auth/login",
	"/api/system/config",
}

// isAllowedDuringSetup reports whether a request path should bypass the setup
// gate. This includes the setup page itself, static assets, health checks, and
// the minimal set of API routes needed to perform initial configuration.
func isAllowedDuringSetup(path string) bool {
	if path == "/setup" || path == "/setup/" {
		return true
	}
	if strings.HasPrefix(path, "/static/") || path == "/health" || path == "/favicon.ico" {
		return true
	}
	for _, route := range setupAllowedAPIRoutes {
		if path == route || strings.HasPrefix(path, route+"/") {
			return true
		}
	}
	return false
}

func setupRedirectMiddleware(cfg *Config) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			path := c.Request().URL.Path

			if isAllowedDuringSetup(path) {
				return next(c)
			}

			if !isSetupComplete(cfg) {
				if strings.HasPrefix(path, "/api/") {
					return c.JSON(http.StatusServiceUnavailable, map[string]string{
						"error": "Server setup is not complete. Configure an admin account and base_url via the setup wizard or API.",
					})
				}
				return c.Redirect(http.StatusFound, "/setup")
			}

			return next(c)
		}
	}
}

func registerSetupRoutes(cfg *Config) {
	e := cfg.Echo

	e.GET("/setup", func(c *echo.Context) error {
		if isSetupComplete(cfg) {
			return c.Redirect(http.StatusFound, "/")
		}
		var buf bytes.Buffer
		if err := templates.Setup().Render(c.Request().Context(), &buf); err != nil {
			log.Printf("Failed to render setup template: %v", err)
			return c.HTML(http.StatusInternalServerError, "Failed to render setup page")
		}
		return c.HTML(http.StatusOK, buf.String())
	})
}
