package controllers_func

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"syncscan-go/locals"
	cryptobox "syncscan-go/locals/gosodium/cryptobox"

	// "golang.org/x/crypto/bcrypt"
	"github.com/dabory/abango-rest"
	e "github.com/dabory/abango-rest/etc"
	"github.com/labstack/echo"
)

type GateTokenGetReq struct {
	ClientId     string
	BeforeBase64 string
	AppBase64    string
}

func GateTokenGet(c echo.Context) error {

	v := c.Get("receiver").(GateTokenGetReq)

	var kPairStr string
	if abango.XConfig["IsLocalKeyPair"] != "Yes" {
		keypair, err := locals.GuestKeyPairGet(v.ClientId)
		if err != nil {
			return c.String(505, e.LogStr("23443rw0dkwk", "Remote KeyPair Failure "+err.Error()))
		}
		kPairStr = keypair
		fmt.Println("RemodeKeypair:", kPairStr)

	} else {
		kPairStr = abango.XConfig["LocalKeyPair"]
		fmt.Println("LocalKeyPair:", kPairStr)
	}

	keyPair, err := base64.StdEncoding.DecodeString(kPairStr)
	if err != nil {
		return c.String(505, e.LogStr("ertjhdssfwew", "Decryption Failure-1 "+err.Error()))
	}

	// locals.ShowDebug("", "Success: KeyPair base64 Decoding")
	// locals.ShowDebug("", "If runtime error: invalid memory address or nil pointer dereference After this")
	sKey, pKey, err := cryptobox.CryptoBoxGetSecretPublicKeyFrom(keyPair)
	if err != nil {
		return c.String(505, e.LogStr("56432d5vd", "Decryption Failure-2:  "+err.Error()))
	}

	var decClientId string
	var ssoSubId int
	if v.AppBase64 != "" {
		decodedStr, err := base64.StdEncoding.DecodeString(v.AppBase64)
		if err != nil {
			return c.String(505, e.LogStr("2l3krhjo21", "AppBase64 Decryption Failure-App1:  "+err.Error()))
		}

		decryptedBytes, boxRet := cryptobox.CryptoBoxSealOpen(decodedStr, pKey, sKey)
		if boxRet != 0 {
			return c.String(505, e.LogStr("65afdfaefad", "AppBase64 Decryption Failure-App2, boxRet: "+strconv.Itoa(boxRet)))
		}
		// fmt.Println("ccc")
		// fmt.Println("decryptedBytes(clientid):", string(decryptedBytes))
		tmpcid := strings.Replace(string(decryptedBytes), "\"", "", -1)

		fmt.Println("clientid:", string(tmpcid))
		if !strings.Contains(tmpcid, ":") {
			decClientId = tmpcid
		} else {
			split := strings.Split(tmpcid, ":")
			if len(split) > 2 {
				return c.String(505, e.LogStr("123p9yhsdoeu", "Too many ':' separators : "+err.Error()))
			}
			decClientId = split[0]
			i, err := strconv.Atoi(split[1])
			if err != nil {
				return c.String(505, e.LogStr("01yhvhd932ur", "SsoSubId is not integer:  "+err.Error()))
			}
			ssoSubId = i
		}

		fmt.Println("ssoSubId:", ssoSubId)
		if v.ClientId != decClientId {
			return c.String(505, e.LogStr("35dswrjuq3d", "AppBase64 ClientId mismatch Failure-App3: "+err.Error()))
		}
	}

	// fmt.Println("v.BeforeBase64", v.BeforeBase64)
	decodedBytes, err := base64.StdEncoding.DecodeString(v.BeforeBase64)
	if err != nil {
		return c.String(505, e.LogStr("4556fdeq3", "Decryption Failure-3:  "+err.Error()))
	}

	//decrypt 문제는 여기서 memory error 가 난다.
	decryptedBytes, boxRet := cryptobox.CryptoBoxSealOpen(decodedBytes, pKey, sKey)
	if boxRet != 0 {
		return c.String(505, e.LogStr("bvsgrere", "Decryption Failure-4(Wrong BB64Key): boxRet:"+strconv.Itoa(boxRet)))
	}

	vmc := &struct {
		Driver   string
		Host     string
		Port     int
		Username string
		Database string
		Password string
	}{}

	if err := json.Unmarshal(decryptedBytes, vmc); err != nil {
		return c.String(505, e.LogStr("2234sdfafae", "Decryption Failure-5: "+err.Error()))
	}

	gtb := &struct {
		abango.GateTokenBase
	}{}

	gtb.ConnString = vmc.Username + ":" + vmc.Password + "@tcp(" + vmc.Host + ":" + e.NumToStr(vmc.Port) + ")/" + vmc.Database

	gtb.ConnString += abango.XConfig["DBOptionString"]
	gtb.SsoSubId = ssoSubId

	gtb.RemoteIp = c.Request().Header.Get("RemoteIp")
	gtb.FrontIp = c.RealIP()
	gtb.FrontHost = c.Request().Header.Get("FrontendHost")
	gtb.Referer = c.Request().Header.Get("Referer")

	gtBytes, _ := json.Marshal(gtb)

	// fmt.Println("ConnString:", gtb.ConnString)
	// fmt.Println("gtBytes:", string(gtBytes))
	gateToken := e.RandString(20)
	// fmt.Println("decryptedString:", string(gtBytes))
	if err := abango.MdbUpdate(gateToken, string(gtBytes)); err != nil {
		return c.String(505, "werqwrqwerqwr-MdbUpdate failed: "+err.Error())
	}

	retv := &struct {
		GateToken string
	}{
		GateToken: gateToken,
	}

	ret, _ := json.Marshal(retv)
	return c.JSONBlob(http.StatusOK, ret)
}

type GateTokenTestReq struct {
	//Function Call Format을 맞추어 주기 위해서
}

func GateTokenTest(c echo.Context) error {

	// if abango.XConfig["IsDevMode"] != "Yes" {
	// 	return c.String(709, "dflajdffdle@/gate-token-test is Only supported in Development Mode !! ")
	// }
	retv := &struct {
		abango.GateTokenBase
	}{}

	if gtbStr, err := abango.MdbView(c.Request().Header.Get("GateToken")); err == nil {
		if err := json.Unmarshal([]byte(gtbStr), retv); err != nil {
			return c.String(700, "323r3f2efd-AfterBase64-Content Format mismatch: "+err.Error())
		}
	} else {
		return c.String(604, "ertvwerawqfd-MdbView failed: "+err.Error())
	}

	// retv.ConnString = "" //보안을 위해서 막음.
	ret, _ := json.Marshal(retv)
	return c.JSONBlob(http.StatusOK, ret)
}
