package dashboard

import (
	"crypto/tls"
	"io"
	"net/http"
	"strings"

	"github.com/gorilla/mux"
	"github.com/rancher/steve/pkg/responsewriter"
	"github.com/rancher/steve/pkg/schemaserver/parse"
	"github.com/sirupsen/logrus"
)

var (
	insecureClient = &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
)

func content(uiSetting func() string) http.Handler {
	return http.FileServer(http.Dir(uiSetting()))
}

func Route(next http.Handler, uiSetting func() string) http.Handler {
	uiContent := responsewriter.NewMiddlewareChain(responsewriter.Gzip,
		responsewriter.DenyFrameOptions,
		responsewriter.CacheMiddleware("json", "js", "css")).Handler(content(uiSetting))

	root := mux.NewRouter()
	root.UseEncodedPath()
	root.Path("/dashboard").HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		rw.Header().Add("Location", "/dashboard/")
		rw.WriteHeader(http.StatusFound)
	})
	root.PathPrefix("/dashboard/assets").Handler(uiContent)
	root.PathPrefix("/dashboard/translations").Handler(uiContent)
	root.PathPrefix("/dashboard/engines-dist").Handler(uiContent)
	root.Handle("/dashboard/asset-manifest.json", uiContent)
	root.Handle("/dashboard/index.html", uiContent)
	root.PathPrefix("/dashboard/").Handler(wrapUI(next, uiSetting))
	root.NotFoundHandler = next

	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		if strings.HasPrefix(req.URL.Path, "/k8s/clusters/local") {
			req.URL.Path = strings.TrimPrefix(req.URL.Path, "/k8s/clusters/local")
			if req.URL.Path == "" {
				req.URL.Path = "/"
			}
		}
		root.ServeHTTP(rw, req)
	})
}

func wrapUI(next http.Handler, uiGetter func() string) http.Handler {
	return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		if parse.IsBrowser(req, true) {
			path := uiGetter()
			if strings.HasPrefix(path, "http") {
				ui(resp, req, path)
			} else {
				http.ServeFile(resp, req, path)
			}
		} else {
			next.ServeHTTP(resp, req)
		}
	})
}

func ui(resp http.ResponseWriter, req *http.Request, url string) {
	if err := serveIndex(resp, req, url); err != nil {
		logrus.Errorf("failed to serve UI: %v", err)
		resp.WriteHeader(500)
	}
}

func serveIndex(resp http.ResponseWriter, req *http.Request, url string) error {
	r, err := insecureClient.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	_, err = io.Copy(resp, r.Body)
	return err
}
