package platform

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"
)

// NewAPIProxy returns an http.Handler suitable for Wails' AssetServer.Handler.
// It reverse-proxies every /api/* request to the remote cdrop backend so the
// embedded web UI keeps using same-origin relative URLs — no CORS, no API-base
// rewrite, no backend change.
//
// Why a proxy instead of cross-origin fetch: the WebView serves the bundle from
// a custom scheme, so a relative /api request never reaches the backend, and a
// cross-origin fetch to https://drop.commilitia.net would need server-side CORS
// the backend doesn't send. Proxying keeps the request same-origin end to end.
//
// SSE (/api/hub/events) streams correctly: FlushInterval=-1 flushes each chunk,
// and the darwin WebView ResponseWriter forwards every Write to the
// WKURLSchemeTask immediately (didReceiveData per write), so frames arrive live.
//
// apiBase is the backend origin, e.g. https://drop.commilitia.net. Requests
// that are not under /api/ get a 404 — desktop navigation is client-side, so the
// asset FS already answers "/" and deep-link misses don't happen in normal use.
func NewAPIProxy(apiBase string) (http.Handler, error) {
	target, err := url.Parse(apiBase)
	if err != nil {
		return nil, fmt.Errorf("proxy: parse api base %q: %w", apiBase, err)
	}
	if target.Scheme == "" || target.Host == "" {
		return nil, fmt.Errorf("proxy: api base %q missing scheme or host", apiBase)
	}

	proxy := httputil.NewSingleHostReverseProxy(target)
	base := proxy.Director
	proxy.Director = func(r *http.Request) {
		base(r)
		// The backend is vhosted behind Caddy; the Host header drives TLS SNI
		// and request routing, so it must be the backend host, not the WebView's
		// synthetic origin.
		r.Host = target.Host
	}
	proxy.FlushInterval = -1 // immediate flush — SSE frames / streamed relay bodies

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if strings.HasPrefix(r.URL.Path, "/api/") {
			proxy.ServeHTTP(w, r)
			return
		}
		http.NotFound(w, r)
	}), nil
}
