package handler

import (
	"bpmsapi/entity"
	"bpmsapi/repository"
	"bpmsapi/service"
	"bpmsapi/util"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

type ApartmentHandler struct {
	logName string
}

func NewApartmentHandler(logName string) *ApartmentHandler {
	return &ApartmentHandler{
		logName: logName,
	}

}
func (apartmenthandler *ApartmentHandler) AddApartmentHandler(c *gin.Context) {
	var response entity.CustomResponse

	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		response.Message = "Problem in Database connection. Please try again"
		response.Resultcode = 1
		c.Set("response", response)
		return
	}

	body := entity.AddApartmentInput{}

	if err := c.ShouldBind(&body); err != nil && err != io.EOF {
		switch err.(type) {
		case validator.ValidationErrors:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.(validator.ValidationErrors).Translate(util.Trans),
			})
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.Error()})
		}

		return

	} else {
		if err != nil && err == io.EOF {
			if util.CheckRequired(body) {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Mandatory input fields missing"})
				return
			}
		}
	}
	body = util.Default_tag(body).(entity.AddApartmentInput)

	var image_path, img_path string
	if body.Apartment_Image != nil {
		file, err1 := c.FormFile("apartment_img")

		if err1 != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, err1)
			return
		}
		if file == nil {
			errMsg := "No file uploaded for apartment_img"
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": errMsg})
			return
		}

		timestamp := time.Now().Unix()
		imageName := fmt.Sprintf("%d%s", timestamp, file.Filename)

		image_path = fmt.Sprintf("./var/www/html/bashyam/assets/apartment_image/%s", imageName)
		img_path = fmt.Sprintf("http://151.106.120.127/bashyam/assets/apartment_image/%s", imageName)
		// image_path = fmt.Sprintf("apartment_image/%s", imageName)
		if err2 := c.SaveUploadedFile(file, image_path); err != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, err2)
			return
		}

	}
	tx, _ := db.Beginx()
	apartmentRepository := repository.ApartmentRepositoryInit(tx)
	apartmentService := service.ApartmentServiceInit(apartmentRepository, tx)
	response = apartmentService.AddNewApartment(body, img_path)

	c.Set("response", response)
}

func (apartmenthandler *ApartmentHandler) GetApartmentHandler(c *gin.Context) {

	var response entity.CustomResponse
	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}

	if err != nil {
		response.Message = "Problem in Database connection. Please try again"
		response.Resultcode = 1
		c.Set("response", response)
		return
	}

	body := entity.GetApartmentDetailsInput{}
	if err := c.Bind(&body); err != nil && err != io.EOF {
		switch err.(type) {
		case validator.ValidationErrors:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.(validator.ValidationErrors).Translate(util.Trans),
			})
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
		return
	}

	body = util.Default_tag(body).(entity.GetApartmentDetailsInput)
	tx, _ := db.Beginx()
	apartmentRepository := repository.ApartmentRepositoryInit(tx)
	apartmentService := service.ApartmentServiceInit(apartmentRepository, tx)
	response = apartmentService.GetApartment(body)
	c.Set("response", response)
}

func (apartmenthandler *ApartmentHandler) UpdateApartmentHandler(c *gin.Context) {
	var response entity.CustomResponse

	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		response.Message = "Problem in Database connection. Please try again"
		response.Resultcode = 1
		c.Set("response", response)
		return
	}

	body := entity.UpdateApartmentInput{}

	if err := c.ShouldBind(&body); err != nil && err != io.EOF {
		switch err.(type) {
		case validator.ValidationErrors:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.(validator.ValidationErrors).Translate(util.Trans),
			})
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.Error()})
		}

		return

	} else {
		if err != nil && err == io.EOF {
			if util.CheckRequired(body) {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Mandatory input fields missing"})
				return
			}
		}
	}
	body = util.Default_tag(body).(entity.UpdateApartmentInput)

	var image_path, img_path string
	if body.Apartment_Image != nil {
		file, err1 := c.FormFile("apartment_img")

		if err1 != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, err1)
			return
		}
		if file == nil {
			errMsg := "No file uploaded for apartment_img"
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": errMsg})
			return
		}

		timestamp := time.Now().Unix()
		imageName := fmt.Sprintf("%d%s", timestamp, file.Filename)
		img_path = fmt.Sprintf("http://151.106.120.127/bashyam/assets/apartment_image/%s", imageName)
		image_path = fmt.Sprintf("./var/www/html/bashyam/assets/apartment_image/%s", imageName)
		// image_path = fmt.Sprintf("apartment_image/%s", imageName)

		if err2 := c.SaveUploadedFile(file, image_path); err != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, err2)
			return
		}
	}
	var banner_imgs []string
	if body.Banner != nil {
		form, err1 := c.MultipartForm()

		if err1 != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, err1)
			return
		}
		files := form.File["banner"]
		if len(files) == 0 {
			errMsg := "No files uploaded"
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": errMsg})
			return
		}
		if len(files) > 3 {
			errMsg := "The maximum number of images you can upload is three"
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": errMsg})
			return
		}
		for _, file := range files {
			timestamp := time.Now().Unix()
			imageName := fmt.Sprintf("%d%s", timestamp, file.Filename)
			banner_img := fmt.Sprintf("http://151.106.120.127/bashyam/assets/banner_image/%s", imageName)
			img_path_save := fmt.Sprintf("./var/www/html/bashyam/assets/banner_image/%s", imageName)
			log.Println("servicerequesthandler : CreateServiceRequest : imagename:", imageName)

			if err2 := c.SaveUploadedFile(file, img_path_save); err2 != nil {
				c.AbortWithStatusJSON(http.StatusBadRequest, err2)
				return
			}
			banner_imgs = append(banner_imgs, banner_img)
		}
	}

	tx, _ := db.Beginx()
	apartmentRepository := repository.ApartmentRepositoryInit(tx)
	apartmentService := service.ApartmentServiceInit(apartmentRepository, tx)
	response = apartmentService.UpdateApartment(body, img_path, banner_imgs)
	c.Set("response", response)
}

func (apartmenthandler *ApartmentHandler) UserApartmentMappingHandler(c *gin.Context) {
	var response entity.CustomResponse
	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		response.Message = "Problem in Database connection. Please try again " + err.Error()
		response.Resultcode = 1
		c.Set("response", response)
		return

	}
	body := entity.UserApartmentMappingInput{}
	// using BindJson method to serialize body with struct
	if err := c.ShouldBindJSON(&body); err != nil && err != io.EOF {
		log.Println(err.Error())
		switch err.(type) {
		case validator.ValidationErrors:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.(validator.ValidationErrors).Translate(util.Trans),
			})
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
		return
	} else {
		if err != nil && err == io.EOF {
			fmt.Println(err.Error())
			if util.CheckRequired(body) {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Mandatory input fields missing"})
				return
			}
		}
	}
	body = util.Default_tag(body).(entity.UserApartmentMappingInput)

	tx, _ := db.Beginx()
	apartmentRepository := repository.ApartmentRepositoryInit(tx)
	apartmentService := service.ApartmentServiceInit(apartmentRepository, tx)
	response = apartmentService.ApartmentUserMapping(body)
	c.Set("response", response)
}

func (apartmenthandler *ApartmentHandler) UserApartmentUpdateHandler(c *gin.Context) {
	var response entity.CustomResponse
	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		response.Message = "Problem in Database connection. Please try again " + err.Error()
		response.Resultcode = 1
		c.Set("response", response)
		return
	}
	body := entity.UserApartmentUpdateInput{}
	// using BindJson method to serialize body with struct
	if err := c.ShouldBindJSON(&body); err != nil && err != io.EOF {
		log.Println(err.Error())
		switch err.(type) {
		case validator.ValidationErrors:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"error": err.(validator.ValidationErrors).Translate(util.Trans),
			})
		default:
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
		return
	} else {
		if err != nil && err == io.EOF {
			fmt.Println(err.Error())
			if util.CheckRequired(body) {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Mandatory input fields missing"})
				return
			}
		}
	}
	body = util.Default_tag(body).(entity.UserApartmentUpdateInput)

	tx, _ := db.Beginx()
	apartmentRepository := repository.ApartmentRepositoryInit(tx)
	apartmentService := service.ApartmentServiceInit(apartmentRepository, tx)
	response = apartmentService.UpdateUserApartment(body)
	c.Set("response", response)
}
