package routebuildermdl

import (
	"errors"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"strings"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"

	"github.com/gin-gonic/gin"
)

func Init(o, r, c *gin.RouterGroup) {
	o.POST("/mql", OpenHandler)
	r.POST("/mql", RestrictedHandler)
	c.POST("/mql", RoleBasedHandler)
}

func setResponseHeader(serviceName string) responseData {
	rd := responseData{}
	val, ok := GetResponseHeader(serviceName)
	if ok {
		rd.ResponseHeader = val
	} else {
		loggermdl.LogError("Service not Found")
	}
	return rd
}

func isMultipartRequest(header string) bool {
	return strings.HasPrefix(header, "multipart/form-data")
}
func isFormRequest(header string) bool {
	return strings.HasPrefix(header, "application/x-www-form-urlencoded")

}

func executeService(name string, data []byte, isForm bool, formData *multipart.Form, isRestricted bool) (interface{}, error) {
	var service interface{}
	var found bool
	if isRestricted {
		service, found = restrictedServices.Get(name)
	} else {
		service, found = openServices.Get(name)
	}
	loggermdl.LogInfo(service, found, name, isRestricted)
	if !found {
		return nil, errors.New("Service Not Found: " + name)
	}

	if isForm {
		serviceCache := service.(ServiceCache)
		return serviceCache.FormService(formData)
	}
	serviceCache := service.(ServiceCache)
	if serviceCache.IsFormService {
		return nil, errors.New("Form_Header_Missing")
	}
	if serviceCache.IsMasterService {
		return serviceCache.MasterService.Run(nil)
	}
	return serviceCache.Service(data)
}

func commonHandler(c *gin.Context, isRestricted bool) {
	service := c.Request.Header.Get("Service-Header")
	header := c.Request.Header.Get("Content-Type")
	responseDataObj := setResponseHeader(service)
	if isMultipartRequest(header) {
		form, multiPartError := c.MultipartForm()
		if multiPartError != nil {
			responseDataObj.Error = multiPartError.Error()
			c.JSON(http.StatusExpectationFailed, responseDataObj)
			return
		}
		result, err := executeService(service, nil, true, form, isRestricted)
		if err != nil {
			responseDataObj.Error = err.Error()
			c.JSON(http.StatusExpectationFailed, responseDataObj)
			return
		}
		responseDataObj.Result = result
		c.JSON(http.StatusOK, responseDataObj)
		return
	}
	reqBody, readError := ioutil.ReadAll(c.Request.Body)
	if readError != nil {
		responseDataObj.Error = readError.Error()
		c.JSON(http.StatusExpectationFailed, responseDataObj)
		return
	}
	result, err := executeService(service, reqBody, false, nil, isRestricted)
	if err != nil {
		responseDataObj.Error = err.Error()
		c.JSON(http.StatusExpectationFailed, responseDataObj)
		return
	}
	responseDataObj.Result = result
	c.JSON(http.StatusOK, responseDataObj)
	return

}

func OpenHandler(c *gin.Context) {
	commonHandler(c, false)
}

func RestrictedHandler(c *gin.Context) {
	commonHandler(c, true)
}

func RoleBasedHandler(c *gin.Context) {
	commonHandler(c, true)
}