// Package web provides HTTP handlers for serving the web UI.
package web

import (
	"embed"
	"html/template"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"path"
	"strings"

	"github.com/la5nta/pat/internal/buildinfo"

	"github.com/gorilla/mux"
)

//go:embed dist/**
var embeddedFS embed.FS

func devServerAddr() string { return strings.TrimSuffix(os.Getenv("PAT_WEB_DEV_ADDR"), "/") }

// DistHandler returns an HTTP handler that serves the static files for the web UI.
func DistHandler() http.Handler {
	switch target := devServerAddr(); {
	case target != "":
		targetURL, err := url.Parse(target)
		if err != nil {
			log.Fatalf("invalid proxy target URL: %v", err)
		}
		return httputil.NewSingleHostReverseProxy(targetURL)
	default:
		return http.FileServer(http.FS(embeddedFS))
	}
}

// UIHandler returns an HTTP handler that serves the UI pages with the given callsign.
func UIHandler(mycall string) http.Handler {
	r := mux.NewRouter()
	r.HandleFunc("/ui", templateHandler("dist/index.html", mycall)).Methods("GET")
	r.HandleFunc("/ui/config", templateHandler("dist/config.html", mycall)).Methods("GET")
	r.HandleFunc("/ui/template", templateHandler("dist/template.html", mycall)).Methods("GET")
	return r
}

func templateHandler(templatePath string, mycall string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// Redirect to config if no callsign is set and we're not already on config page
		if mycall == "" && r.URL.Path != "/ui/config" {
			http.Redirect(w, r, "/ui/config", http.StatusFound)
			return
		}
		t, err := loadTemplate(templatePath)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		tmplData := struct{ AppName, Version, Mycall string }{buildinfo.AppName, buildinfo.VersionString(), mycall}
		if err := t.Execute(w, tmplData); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

func loadTemplate(templatePath string) (*template.Template, error) {
	if devServer := devServerAddr(); devServer != "" {
		// Dev mode: fetch from dev server
		resp, err := http.Get(devServer + "/" + templatePath)
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		data, err := io.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		return template.New(path.Base(templatePath)).Parse(string(data))
	}

	// Load from embedded FS
	return template.ParseFS(embeddedFS, templatePath)
}
