package util

import (
	"bpmsapi/entity"
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"net/http"

	"os"
	"reflect"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	ut "github.com/go-playground/universal-translator"
	"gopkg.in/yaml.v2"
)

var Environment string
var Port string
var Trans ut.Translator


type TokenModel struct {
	token *string `json:"token"`
}

func GenerateOTP() int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(9999-1000) + 1000
}


func LoadConfiguration() (*entity.Config, error) {
	// Create config structure
	var configPath string
	if Environment == "test" {
		configPath = "/var/www/bpms_api_backend/appconfig_test.yml"
	} else if Environment == "local" {
		configPath = "appconfig_local.yml"
	} else if Environment == "production" {
		configPath = "/var/www/bpms_api_backend/appconfig.yml"
	}
	config := &entity.Config{}

	// Open config file
	file, err := os.Open(configPath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	// Init new YAML decode
	d := yaml.NewDecoder(file)

	// Start YAML decoding from file
	if err := d.Decode(&config); err != nil {
		return nil, err
	}

	return config, nil
}


func FormatResult(c *gin.Context, token *string) {
	response, bool := c.Get("response")
	fmt.Print(response)
	if bool {
		res := response.(entity.CustomResponse)
		resBytes, _ := json.Marshal(res)
		log.Println("GeneralUtility: FormatResult: Outputpayload: ", string(resBytes))
		if res.Token != nil {
			token = res.Token
			res.Token = nil
		}
		c.JSON(http.StatusOK, gin.H{"response": res, "token": token})
	} else {
		if !c.IsAborted() {
			c.JSON(http.StatusInternalServerError, gin.H{"response": "Server error. Please check with the admin."})
		}
	}
}

func Default_tag(t interface{}) interface{} {
	switch t.(type) {
	case entity.StateListInput:
		val := t.(entity.StateListInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.CityListInput:
		val := t.(entity.CityListInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.CreateRequestInput:
		val := t.(entity.CreateRequestInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.FetchServicesInput:
		val := t.(entity.FetchServicesInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.ApartmentListInput:
		val := t.(entity.ApartmentListInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.InitConfigInput:
		val := t.(entity.InitConfigInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.UserFetchInput:
		val := t.(entity.UserFetchInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.AddStateInput:
		val := t.(entity.AddStateInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.AdminAuthInput:
		val := t.(entity.AdminAuthInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.AddCityInput:
		val := t.(entity.AddCityInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.AddApartmentInput:
		val := t.(entity.AddApartmentInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.FetchProblemCategoryInput:
		val := t.(entity.FetchProblemCategoryInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.GetProblemDescriptionInput:
		val := t.(entity.GetProblemDescriptionInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.AddServiceInput:
		val := t.(entity.AddServiceInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.GetApartmentDetailsInput:
		val := t.(entity.GetApartmentDetailsInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.UpdateEmployeeProfileInput:
		val := t.(entity.UpdateEmployeeProfileInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.SuperAdminDashboardInput:
		val := t.(entity.SuperAdminDashboardInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.FetchServiceRequestInput:
		val := t.(entity.FetchServiceRequestInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		return val
	case entity.GetAllUsersInput:
		val := t.(entity.GetAllUsersInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}

		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		if val.PageLimit == 0 {
			f, _ := typ.FieldByName("PageLimit")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.PageLimit = int(defVal)
		}
		return val

	case entity.GetAdminListInput:
		val := t.(entity.GetAdminListInput)
		typ := reflect.TypeOf(val)

		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		if val.PageLimit == 0 {
			f, _ := typ.FieldByName("PageLimit")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.PageLimit = int(defVal)
		}
		return val

	case entity.GetTechnicianListInput:
		val := t.(entity.GetTechnicianListInput)
		typ := reflect.TypeOf(val)

		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		if val.PageLimit == 0 {
			f, _ := typ.FieldByName("PageLimit")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.PageLimit = int(defVal)
		}
		return val
	case entity.UpdateApartmentInput:
		val := t.(entity.UpdateApartmentInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.UpdateProblemCategoryInput:
		val := t.(entity.UpdateProblemCategoryInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}

		return val
	case entity.UpdateSrqTechInput:
		val := t.(entity.UpdateSrqTechInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.SignUpAdminInput:
		val := t.(entity.SignUpAdminInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Is_Available)
		if val.Is_Available == 0 {
			f, _ := typ.FieldByName("Is_Available")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Is_Available = int(defVal)
		}
		return val
	case entity.UpdateSrqCostInput:
		val := t.(entity.UpdateSrqCostInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.CreateChildServiceRequestInput:
		val := t.(entity.CreateChildServiceRequestInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.UpdateServiceRequestInput:
		val := t.(entity.UpdateServiceRequestInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.UserApartmentMappingInput:
		val := t.(entity.UserApartmentMappingInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.UserApartmentUpdateInput:
		val := t.(entity.UserApartmentUpdateInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val
	case entity.UpdateServiceRequestAdminInput:
		val := t.(entity.UpdateServiceRequestAdminInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}

		return val

	case entity.AddFeedback:
		val := t.(entity.AddFeedback)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}

		return val

	case entity.UpdateQuotationDetailsInput:
		val := t.(entity.UpdateQuotationDetailsInput)
		typ := reflect.TypeOf(val)
		log.Print(val.Language_Code)
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}

		return val
	case entity.GetAllEmployeeInput:
		val := t.(entity.GetAllEmployeeInput)
		typ := reflect.TypeOf(val)

		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		if val.PageLimit == 0 {
			f, _ := typ.FieldByName("PageLimit")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.PageLimit = int(defVal)
		}
		if val.Language_Code == 0 {
			f, _ := typ.FieldByName("Language_Code")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Language_Code = int(defVal)
		}
		return val

	case entity.FetchTechnicianInput:
		val := t.(entity.FetchTechnicianInput)
		typ := reflect.TypeOf(val)
		if val.Page == 0 {
			f, _ := typ.FieldByName("Page")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.Page = int(defVal)
		}
		if val.PageLimit == 0 {
			f, _ := typ.FieldByName("PageLimit")
			defVal, _ := strconv.ParseInt(f.Tag.Get("default"), 10, 64)
			log.Print(f.Tag.Get("default"))
			val.PageLimit = int(defVal)
		}
		return val
	default:
		return ""
	}
}

func CheckRequired(t interface{}) bool {
	typ := reflect.TypeOf(t)
	for i := 0; i < typ.NumField(); i++ {
		f := typ.Field(i)
		bindingVal, isAvail := f.Tag.Lookup("binding")
		if isAvail {
			if bindingVal == "required" {
				return true
			}
		}
	}
	return false
}
