package web

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"

	"git.jmbit.de/jmb/podterminal/pods"
)

func createReverseProxy(backendService string) (*httputil.ReverseProxy, error) {
	var err error
	log.Println("Creating reverse Proxy for ", backendService)

	backendURL, err := url.Parse(backendService)
	if err != nil {
		log.Printf("Could not parse backend URL: %v", err)
	}

	proxy := &httputil.ReverseProxy{
		Rewrite: func(request *httputil.ProxyRequest) {
			request.SetURL(backendURL)
			request.Out.Host = request.In.Host
		},
		ModifyResponse: func(response *http.Response) error {
			if response.StatusCode == http.StatusBadGateway {
				time.Sleep(time.Second)
				response.StatusCode = 307
				response.Header.Set("Location", "/")

			}
			return nil
		},
	}

	return proxy, err
}

func containerProxy(c *gin.Context) {
	session := sessions.Default(c)
	sessionID := ""
	if session.Get("ct") == nil && session.Get("ready") == nil {
		session.Set("ready", false)
		session.Save()
		log.Println("Creating Container for Session ", sessionID)
		ct, err := pods.CreateContainer()
		session.Set("ct", ct)
		session.Save()
		if err != nil {
			c.HTML(500, "Error", fmt.Sprintf("[%s] Could not create Container: %v", sessionID, err))
			session.Delete("ct")
			session.Save()
			c.Abort()
		}
		err = pods.StartContainer(ct)
		if err != nil {
			c.HTML(500, "Error", fmt.Sprintf("[%s] Could not start Container: %v", sessionID, err))
			session.Delete("ct")
			session.Save()
			c.Abort()
		}

		ctip, err := pods.GetContainerIP(ct)

		if err != nil {
			c.HTML(500, "Error", fmt.Sprintf("[%s] Could not get Container ip: %v", sessionID, err))
			session.Delete("ct")
			session.Save()
			c.Abort()
		}

		// Soft fail Skel
		// _ = pods.CopySkelToContainer(ct)

		proxies[ct], err = createReverseProxy(
			fmt.Sprintf("http://%s:%d", ctip, viper.GetInt("container_port")),
		)

		if err != nil {
			c.HTML(
				500,
				"Error",
				fmt.Sprintf("[%s] Could not create Container Proxy: %v", sessionID, err),
			)
			session.Delete("ct")
			session.Save()
			c.Abort()
		}
		session.Set("ready", true)
		session.Save()
		c.Redirect(307, "/")
	} else {
		sessionCT := session.Get("ct")
		switch sessionCT.(type) {
		case string:

		default:
			c.HTML(500, "Error", "Session Container ID is not a string")
			session.Delete("ct")
			session.Delete("ready")
			session.Save()
			c.Abort()
		}
		if session.Get("ready").(bool) == false {
			time.Sleep(time.Second)
			c.Redirect(307, "/")
		}
		id := session.Get("ct").(string)
		proxy := proxies[id]
		if proxy != nil {
			proxy.ServeHTTP(c.Writer, c.Request)
		} else {
			session.Delete("ct")
			session.Delete("ready")
			session.Save()
			c.Abort()
		}

	}

}
