package User

import (
	"net/http"

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

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

///////////////////////////////////////////////////////////
// Horoscope Controller
///////////////////////////////////////////////////////////

type HoroscopeController struct {
	service services.HoroscopeService
}

func NewHoroscopeController(service services.HoroscopeService) *HoroscopeController {
	return &HoroscopeController{service: service}
}

// caller identifies the customer and the client for the horoscope_requests
// log; see services.ResolveHoroscopeClient for where each value comes from.
func (c *HoroscopeController) caller(ctx *gin.Context, client dto.ClientInfo) dto.HoroscopeCaller {

	caller := dto.HoroscopeCaller{
		UserID:     ctx.MustGet("user_id").(uint),
		ActorType:  services.HoroscopeActorCustomer,
		IPAddress:  ctx.ClientIP(),
		Chargeable: true,
	}

	services.ResolveHoroscopeClient(&caller, ctx.GetHeader, client, []string{
		services.HoroscopePlatformCustomerApp,
		services.HoroscopePlatformWeb,
	})

	// Set by middleware.TrackAstrologyService when the admin prices this call.
	if value, ok := ctx.Get(services.AstroPriceContextKey); ok {

		if price, ok := value.(float64); ok {
			caller.CataloguePrice = &price
		}
	}

	return caller
}

///////////////////////////////////////////////////////////
// Daily
///////////////////////////////////////////////////////////

func (c *HoroscopeController) Daily(ctx *gin.Context) {

	var request dto.DailyHoroscopeRequest

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

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

		return
	}

	response, err := c.service.Daily(c.caller(ctx, request.ClientInfo), request)

	if err != nil {

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

		return
	}

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

///////////////////////////////////////////////////////////
// Daily Moon
///////////////////////////////////////////////////////////

func (c *HoroscopeController) DailyMoon(ctx *gin.Context) {

	var request dto.DailyHoroscopeRequest

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

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

		return
	}

	response, err := c.service.DailyMoon(c.caller(ctx, request.ClientInfo), request)

	if err != nil {

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

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("Daily moon horoscope fetched successfully.", response),
	)
}

///////////////////////////////////////////////////////////
// Weekly
///////////////////////////////////////////////////////////

func (c *HoroscopeController) Weekly(ctx *gin.Context) {

	var request dto.WeeklyHoroscopeRequest

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

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

		return
	}

	response, err := c.service.Weekly(c.caller(ctx, request.ClientInfo), request)

	if err != nil {

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

		return
	}

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

///////////////////////////////////////////////////////////
// Yearly
///////////////////////////////////////////////////////////

func (c *HoroscopeController) Yearly(ctx *gin.Context) {

	var request dto.YearlyHoroscopeRequest

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

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

		return
	}

	response, err := c.service.Yearly(c.caller(ctx, request.ClientInfo), request)

	if err != nil {

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

		return
	}

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

///////////////////////////////////////////////////////////
// Daily Nakshatra
///////////////////////////////////////////////////////////

func (c *HoroscopeController) DailyNakshatra(ctx *gin.Context) {

	var request dto.DailyNakshatraRequest

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

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

		return
	}

	response, err := c.service.DailyNakshatra(c.caller(ctx, request.ClientInfo), request)

	if err != nil {

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

		return
	}

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

///////////////////////////////////////////////////////////
// Feedback
///////////////////////////////////////////////////////////

func (c *HoroscopeController) Feedback(ctx *gin.Context) {

	var request dto.HoroscopeFeedbackRequest

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

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

		return
	}

	if err := c.service.Feedback(c.caller(ctx, request.ClientInfo), request); err != nil {

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

		return
	}

	ctx.JSON(http.StatusOK, helpers.SuccessResponse("Feedback submitted", nil))
}

///////////////////////////////////////////////////////////
// Signs
///////////////////////////////////////////////////////////

// Signs lists the zodiac signs for the sign picker. Send each sign's `zodiac`
// (1..12) to the prediction endpoints, never its `sign_id`.
func (c *HoroscopeController) Signs(ctx *gin.Context) {

	signs, err := c.service.Signs()

	if err != nil {

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

		return
	}

	ctx.JSON(http.StatusOK, helpers.SuccessResponse("Horoscope signs fetched successfully.", signs))
}
