// Package web embeds the SvelteKit SPA build output and serves it over HTTP.
// Requests for real files under build/ are served verbatim; anything else —
// deep links like /artists/abc, missing asset paths — returns build/index.html
// so the SPA can resolve the route client-side.
package web

import (
	"embed"
	"io/fs"
	"net/http"
	"path"
	"strings"

	"git.fabledsword.com/bvandeusen/minstrel/internal/config"
)

//go:embed all:build
var buildFS embed.FS

// Handler returns an http.Handler that serves the embedded SPA.
//
// Behavior:
//   - GET /                              -> build/index.html
//   - GET /<path that exists in build/>  -> that file, via http.FileServer
//   - GET /<anything else>               -> build/index.html (SPA fallback)
//
// Callers are expected to register this as the router's NotFound/catch-all so
// explicitly-routed paths (like /api/* and /rest/*) take precedence.
//
// The branding parameter is applied to index.html once at construction via
// html/template; all requests serve the resulting cached bytes.
func Handler(branding config.BrandingConfig) http.Handler {
	sub, err := fs.Sub(buildFS, "build")
	if err != nil {
		// fs.Sub on a valid embed path can only fail if the embed directive
		// is malformed, which the compile would have caught.
		panic("web: fs.Sub(build) failed: " + err.Error())
	}

	raw, err := fs.ReadFile(sub, "index.html")
	if err != nil {
		panic("web: embedded build/index.html missing: " + err.Error())
	}

	index, err := applyBrandingTemplate(string(raw), branding)
	if err != nil {
		panic("web: branding template failed: " + err.Error())
	}

	fileServer := http.FileServer(http.FS(sub))

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		clean := path.Clean(r.URL.Path)
		if clean == "/" || clean == "." {
			serveIndex(w, index)
			return
		}
		name := strings.TrimPrefix(clean, "/")
		if info, err := fs.Stat(sub, name); err == nil && !info.IsDir() {
			fileServer.ServeHTTP(w, r)
			return
		}
		serveIndex(w, index)
	})
}

func serveIndex(w http.ResponseWriter, index []byte) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Header().Set("Cache-Control", "no-cache")
	_, _ = w.Write(index)
}
