package Astrologer

import (
	"net/http"

	"github.com/gin-gonic/gin"

	dto_astrologer "astrology-api/dto_astrologer"
	"astrology-api/helpers"
	services_astrologer "astrology-api/services_astrologer"
)

type AuthController struct {
	service services_astrologer.AuthService
}

func NewAuthController() *AuthController {
	return &AuthController{
		service: services_astrologer.NewAuthService(),
	}

}

func (c *AuthController) Register(ctx *gin.Context) {
	var req dto_astrologer.RegisterRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	response, err := c.service.Register(req)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Astrologer registered successfully. OTP sent.",
			response,
		),
	)

}

func (c *AuthController) VerifyMobileOTP(ctx *gin.Context) {

	var req dto_astrologer.VerifyMobileOTPRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	response, err := c.service.VerifyMobileOTP(req)

	if err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("Mobile verified successfully", response),
	)

}

func (c *AuthController) VerifyEmailOTP(ctx *gin.Context) {

	var req dto_astrologer.VerifyEmailOTPRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	response, err := c.service.VerifyEmailOTP(req)

	if err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("Email verified successfully", response),
	)
}

func (c *AuthController) ResendOTP(ctx *gin.Context) {

	var req dto_astrologer.ResendOTPRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	response, err := c.service.ResendOTP(req)

	if err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("OTP resent successfully.", response),
	)
}

func (c *AuthController) Login(ctx *gin.Context) {

	var req dto_astrologer.LoginRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}
	response, err := c.service.Login(req)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, helpers.ErrorResponse(err.Error()))
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"OTP sent successfully.",
			response,
		),
	)
}

func (c *AuthController) VerifyLoginOTP(ctx *gin.Context) {
	var req dto_astrologer.VerifyOTPRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	response, err := c.service.VerifyLoginOTP(req)
	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Login successful.",
			response,
		),
	)
}

func (c *AuthController) ResendLoginOTP(ctx *gin.Context) {

	var req dto_astrologer.ResendOTPRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	response, err := c.service.ResendOTP(req)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"OTP resent successfully.",
			response,
		),
	)
}

func (c *AuthController) RefreshToken(ctx *gin.Context) {

	var req dto_astrologer.RefreshTokenRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	response, err := c.service.RefreshToken(req)

	if err != nil {

		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Token refreshed successfully.",
			response,
		),
	)
}

func (c *AuthController) Logout(ctx *gin.Context) {

	userIDValue, exists := ctx.Get("user_id")

	if !exists {
		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("unauthorized"),
		)
		return
	}

	userID, ok := userIDValue.(uint)

	if !ok {
		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("invalid user"),
		)
		return
	}

	response, err := c.service.Logout(userID)

	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Logout successful.",
			response,
		),
	)
}

func (c *AuthController) GetLoggedInProfile(ctx *gin.Context) {

	userIDValue, exists := ctx.Get("user_id")

	if !exists {

		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("Unauthorized"),
		)

		return
	}

	userID, ok := userIDValue.(uint)

	if !ok {

		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("Invalid user"),
		)

		return
	}

	response, err := c.service.GetLoggedInProfile(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Profile fetched successfully.",
			response,
		),
	)
}

func (c *AuthController) UpdateDeviceToken(ctx *gin.Context) {
	var req dto_astrologer.UpdateDeviceTokenRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	userIDValue, exists := ctx.Get("user_id")
	if !exists {
		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("Unauthorized"),
		)
		return
	}
	userID, ok := userIDValue.(uint)
	if !ok {
		ctx.JSON(
			http.StatusUnauthorized,
			helpers.ErrorResponse("Invalid user"),
		)
		return
	}
	response, err := c.service.UpdateDeviceToken(userID, req)
	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Device token updated successfully.",
			response,
		),
	)
}
