package User

import (
	"errors"
	"net/http"
	"strconv"

	"astrology-api/dto"
	services "astrology-api/services"

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

type WalletController struct {
	walletService services.WalletService
}

func NewWalletController(walletService services.WalletService) *WalletController {

	return &WalletController{
		walletService: walletService,
	}
}

func (c *WalletController) GetWalletTransactions(ctx *gin.Context) {

	var request dto.WalletTransactionRequest

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

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

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

	if !exists {

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
			"status":  401,
		})
		return
	}

	var userID uint

	switch v := userIDValue.(type) {

	case uint:
		userID = v

	case int:
		userID = uint(v)

	case float64:
		userID = uint(v)

	case string:

		id, err := strconv.Atoi(v)
		if err != nil {

			ctx.JSON(http.StatusUnauthorized, gin.H{
				"message": "Invalid User",
				"status":  401,
			})
			return
		}

		userID = uint(id)

	default:

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
			"status":  401,
		})
		return
	}

	response, err := c.walletService.GetWalletTransactions(
		userID,
		request,
	)

	if err != nil {

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

	ctx.JSON(http.StatusOK, response)
}

func (c *WalletController) GetWalletTransactionDetail(ctx *gin.Context) {

	var request dto.WalletTransactionDetailRequest

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

		ctx.JSON(http.StatusBadRequest, gin.H{
			"message": "id and transactionType are required",
			"status":  400,
		})
		return
	}

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

	if !exists || !ok {

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
			"status":  401,
		})
		return
	}

	response, err := c.walletService.GetWalletTransactionDetail(userID, request)

	if errors.Is(err, gorm.ErrRecordNotFound) {

		ctx.JSON(http.StatusNotFound, gin.H{
			"message": "Transaction not found",
			"status":  404,
		})
		return
	}

	if err != nil {

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

	ctx.JSON(http.StatusOK, response)
}

func (c *WalletController) GetWalletSummary(ctx *gin.Context) {

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

	if !exists {

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
			"status":  401,
		})
		return
	}

	var userID uint

	switch v := userIDValue.(type) {

	case uint:
		userID = v

	case int:
		userID = uint(v)

	case float64:
		userID = uint(v)

	case string:

		id, err := strconv.Atoi(v)

		if err != nil {

			ctx.JSON(http.StatusUnauthorized, gin.H{
				"message": "Unauthorized",
				"status":  401,
			})
			return
		}

		userID = uint(id)

	default:

		ctx.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
			"status":  401,
		})
		return
	}

	response, err := c.walletService.GetWalletSummary(userID)

	if err != nil {

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

	ctx.JSON(http.StatusOK, response)
}

func (wc *WalletController) GetRechargeOffers(c *gin.Context) {

	response, err := wc.walletService.GetRechargeOffers()

	if err != nil {

		c.JSON(http.StatusInternalServerError, gin.H{
			"status":  500,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, response)
}

func (wc *WalletController) CreatePayment(c *gin.Context) {

	var req dto.CreatePaymentRequest

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

	userIDValue, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"status":  false,
			"message": "Unauthorized",
		})
		return
	}

	var userID uint

	switch v := userIDValue.(type) {
	case uint:
		userID = v
	case int:
		userID = uint(v)
	case float64:
		userID = uint(v)
	case string:
		id, err := strconv.Atoi(v)
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"status": false, "message": "Invalid User"})
			return
		}
		userID = uint(id)
	default:
		c.JSON(http.StatusUnauthorized, gin.H{"status": false, "message": "Unauthorized"})
		return
	}

	response, err := wc.walletService.CreatePayment(userID, req)

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}

func (wc *WalletController) VerifyPayment(c *gin.Context) {

	var req dto.VerifyPaymentRequest

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

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

		return
	}

	userIDValue, exists := c.Get("userID")
	if !exists {

		c.JSON(http.StatusUnauthorized, gin.H{
			"status":  false,
			"message": "Unauthorized",
		})

		return
	}

	userID := userIDValue.(uint)

	response, err := wc.walletService.VerifyPayment(userID, req)

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}
