package User

import (
	"net/http"

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

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

// socialLogin is shared by the mobile-app and web-app endpoints. A Firebase ID
// token is verified identically for both; the platform only decides what gets
// recorded on the login history and the social account row.
func socialLogin(c *gin.Context, platform string) {

	var req dto.SocialLoginRequest

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

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

		return
	}

	response, err := services.SocialLogin(req, platform, c.ClientIP())

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}

// MobileSocialLogin handles social sign-in from the mobile user app.
func MobileSocialLogin(c *gin.Context) {
	socialLogin(c, services.PlatformMobile)
}

// WebSocialLogin handles social sign-in from the web user app.
func WebSocialLogin(c *gin.Context) {
	socialLogin(c, services.PlatformWeb)
}

// SendSocialMobileOTP sends the mobile OTP for a social account that still has
// to verify a number. Authenticated by the verification token from social login,
// not by a session.
func SendSocialMobileOTP(c *gin.Context) {

	var req dto.SocialSendMobileOTPRequest

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

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

		return
	}

	response, err := services.SendSocialMobileOTP(req)

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}

// VerifySocialMobileOTP completes mobile verification and returns the session.
func VerifySocialMobileOTP(c *gin.Context) {

	var req dto.SocialVerifyMobileOTPRequest

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

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

		return
	}

	response, err := services.VerifySocialMobileOTP(req, c.ClientIP())

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}

// FacebookSocialLogin handles Facebook sign-in from either app. The body carries
// access_token rather than id_token: Facebook issues an opaque bearer token, not
// a JWT, so it is verified against the Graph API instead of a signature.
func FacebookSocialLogin(c *gin.Context) {

	// Defaults to the mobile app. A web client says so with ?platform=web, or
	// with "platform" in the body, which the service honours either way.
	platform := services.PlatformMobile

	if c.Query("platform") == services.PlatformWeb {
		platform = services.PlatformWeb
	}

	socialLogin(c, platform)
}

// SendSocialEmailOTP sends the email OTP for a social account that still has to
// verify an address — a Facebook account registered with a phone number arrives
// without one.
func SendSocialEmailOTP(c *gin.Context) {

	var req dto.SocialSendEmailOTPRequest

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

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

		return
	}

	response, err := services.SendSocialEmailOTP(req)

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}

// VerifySocialEmailOTP completes email verification, and issues the session when
// the mobile step is done too.
func VerifySocialEmailOTP(c *gin.Context) {

	var req dto.SocialVerifyEmailOTPRequest

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

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

		return
	}

	response, err := services.VerifySocialEmailOTP(req, c.ClientIP())

	if err != nil {

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

		return
	}

	c.JSON(http.StatusOK, response)
}
