package infra

import (
	"io/fs"
	"net/http"
	"strings"
)

// SPAHandler retorna un http.Handler que sirve los archivos estáticos de fsys
// y hace fallback a indexFile para cualquier ruta que no corresponda a un
// archivo existente — patrón SPA para React Router y similares.
//
// fsys es típicamente un iofs.Sub(embed.FS, "frontend/dist").
// indexFile es la ruta dentro de fsys del HTML de fallback (ej. "index.html").
func SPAHandler(fsys fs.FS, indexFile string) http.Handler {
	fileServer := http.FileServer(http.FS(fsys))

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Defensa contra path traversal
		if strings.Contains(r.URL.Path, "..") {
			http.Error(w, "invalid path", http.StatusBadRequest)
			return
		}

		// Normalizar: quitar la barra inicial para fs.Stat
		path := strings.TrimPrefix(r.URL.Path, "/")
		if path == "" {
			path = "."
		}

		info, err := fs.Stat(fsys, path)
		if err == nil && !info.IsDir() {
			// El archivo existe y no es directorio: servir normalmente
			fileServer.ServeHTTP(w, r)
			return
		}

		// Fallback a indexFile (ruta no encontrada o directorio)
		data, err := fs.ReadFile(fsys, indexFile)
		if err != nil {
			http.Error(w, "could not read index file", http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		w.WriteHeader(http.StatusOK)
		w.Write(data) //nolint:errcheck
	})
}
