package handlers

import (
	"context"
	"fmt"
	"net/http"
	"strings"

	"codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/actions"
	"codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/messages"
	"codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner/v2/api"
	"codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner/v2/errors"
	"codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner/v2/globals"

	"nhooyr.io/websocket"
	"nhooyr.io/websocket/wsjson"
)

func WebSockerHandler(w http.ResponseWriter, r *http.Request) {
	var (
		err          error
		wsConnection *websocket.Conn
		authUser     string
	)

	xForwardedUser := r.Header["X-Forwarded-User"]
	if globals.Test {
		xForwardedUser = []string{"thomas.bellembois@uca.fr"}
	}

	if len(xForwardedUser) == 0 || xForwardedUser[0] == "" {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	authUser = strings.Split(xForwardedUser[0], "@")[0]
	authUser = strings.ReplaceAll(authUser, ".", "")

	if wsConnection, err = websocket.Accept(w, r, nil); err != nil {
		errors.InternalServerError(w, r, err)
		return
	}
	defer wsConnection.Close(websocket.StatusInternalError, "")

	ctx := context.Background()

	for {
		fmt.Println("waiting for web socket message")

		var (
			message messages.WSMessage
		)

		if err = wsjson.Read(ctx, wsConnection, &message); err != nil {
			errors.InternalServerError(w, r, err)
			return
		}

		fmt.Printf("received: %+v\n", message)

		switch message.Action {
		case actions.GetContainerLog:
			api.GetContainerLog(ctx, wsConnection, message.Container)
		case actions.RemoveContainer:
			api.RemoveContainer(ctx, wsConnection, message.Container, authUser)
		case actions.StartContainer:
			api.StartContainer(ctx, wsConnection, message.Container, authUser)
		case actions.ExecContainer:
			api.ExecContainer(ctx, wsConnection, message.Container, message.Exec, authUser)
		case actions.GetContainers:
			api.GetContainers(ctx, wsConnection, message.Container, authUser)
		case actions.GetConfig:
			api.GetConfig(ctx, wsConnection)
		case actions.Ping:
			api.Pong(ctx, wsConnection)
		case actions.Test:
			api.Test(ctx, wsConnection, message.Container)
		case actions.TestError:
			api.TestError(ctx, wsConnection, message.Container)
		}
	}
}
