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 UserHandler struct {
	logName string
}

func NewUserHandler(logName string) *UserHandler {
	return &UserHandler{
		logName: logName,
	}
}

func (userHandler *UserHandler) InitConfigHandler(c *gin.Context) {
	db, err := util.GetDBConnection()
	var resp entity.CustomResponse
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		resp.Resultcode = 1
		resp.Message = "Problem in establishing database connection"
		c.Set("response", resp)
		return
	}

	body := entity.InitConfigInput{}
	// using BindJson method to serialize body with struct
	if err := c.Bind(&body); err != nil {
		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.InitConfigInput)

	userRepository := repository.UserRepositoryInit(db)
	configRepository := repository.ConfigRepositoryInit(db)
	serviceRepository := repository.ServiceRepositoryInit(db)
	srqRepository := repository.ServiceRequestRepositoryInit(db)
	promoRepository := repository.PromoRepositoryInit(db)
	userService := service.UserServiceInit(userRepository, configRepository, serviceRepository, srqRepository, promoRepository)
	resp = userService.InitConfig(body.Userid, body.ApartmentId, body.Language_Code)
	c.Set("response", resp)
}

func (userHandler *UserHandler) FetchUserHandler(c *gin.Context) {
	db, err := util.GetDBConnection()
	var resp entity.CustomResponse
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		resp.Resultcode = 1
		resp.Message = "Problem in establishing database connection"
		c.Set("response", resp)
		return
	}

	body := entity.UserFetchInput{}
	// using BindJson method to serialize body with struct
	if err := c.Bind(&body); err != nil {
		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.UserFetchInput)
	userRepository := repository.UserRepositoryInit(db)
	configRepository := repository.ConfigRepositoryInit(db)
	userService := service.UserServiceInit(userRepository, configRepository, nil, nil, nil)
	resp = userService.FetchUser(body.Mobno, body.Language_Code)
	c.Set("response", resp)
}

func (userHandler *UserHandler) FetchProblemCategoryHandler(c *gin.Context) {
	db, err := util.GetDBConnection()
	var resp entity.CustomResponse
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		resp.Resultcode = 1
		resp.Message = "Problem in establishing database connection"
		c.Set("response", resp)
		return
	}
	body := entity.FetchProblemCategoryInput{}

	if err := c.Bind(&body); err != nil {
		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.FetchProblemCategoryInput)

	userRepository := repository.UserRepositoryInit(db)
	userService := service.UserServiceInit(userRepository, nil, nil, nil, nil)
	resp = userService.FetchProblemCategory(body)
	c.Set("response", resp)
}

func (userHandler *UserHandler) GetAllUsersHandler(c *gin.Context) {
	db, err := util.GetDBConnection()
	var resp entity.CustomResponse
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		resp.Resultcode = 1
		resp.Message = "Problem in establishing database connection"
		c.Set("response", resp)
		return
	}
	body := entity.GetAllUsersInput{}

	if err := c.Bind(&body); err != nil {
		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.GetAllUsersInput)

	userRepository := repository.UserRepositoryInit(db)
	userService := service.UserServiceInit(userRepository, nil, nil, nil, nil)
	resp = userService.GetAllUsers(body)
	c.Set("response", resp)
}

func (userHandler *UserHandler) UpdateProfileHandler(c *gin.Context) {
	var updateProfileResp entity.CustomResponse
	db, err := util.GetDBConnection()
	if db != nil {
		defer db.Close()
	}
	if err != nil {
		updateProfileResp.Message = "Problem in establishing database connection " + err.Error()
		updateProfileResp.Resultcode = 1
		c.Set("response", updateProfileResp)
		return
	}
	body := entity.UpdateProfileInput{}
	if err := c.ShouldBind(&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 {
			if util.CheckRequired(body) {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Mandatory input fields missing"})
				return
			}
		}
	}

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

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

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

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

	}

	userRepository := repository.UserRepositoryInit(db)
	userService := service.UserServiceInit(userRepository, nil, nil, nil, nil)
	updateProfileResp = userService.UpdateProfileService(body, img_path)
	c.Set("response", updateProfileResp)
}
