package oauth2

import (
	"errors"
	"net/http"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"

	"github.com/tidbcloud/auth-server/commons/errs"
	oauth2_dto "github.com/tidbcloud/auth-server/internal/dto/oauth2"
	"github.com/tidbcloud/tiinf/monitor/tilog"
)

// DeviceAuthorizationEndpoint godoc
//
//	@Summary		Device authorization endpoint.
//	@Description	Device starts the authorization request, get the user_code, device_code and verification_uri.
//	@Tags			oauth2_device_public
//	@Accept			json,x-www-form-urlencoded
//	@Produce		json
//	@Param			client_id	body		oauth2_dto.DeviceAuthorizationRequest	true	"client_id"
//	@Success		200			{object}	oauth2_dto.DeviceAuthorizationResponse
//	@Failure		400			{object}	oauth2_dto.ErrorResponse
//	@Router			/v1/device_authorization [post]
//
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
func (o *Oauth2ControllerImpl) DeviceAuthorizationEndpoint(c *gin.Context) {
	ctx := c.Request.Context()
	var req oauth2_dto.DeviceAuthorizationRequest
	if err := autoBind(c, &req); err != nil {
		tilog.Info(ctx, "autoBind err", zap.Error(err))
		responseWithBadRequest(c, errors.New("bad request body"))
		return
	}
	tilog.Info(ctx, "", zap.Any("req", req))
	if err := req.Validate(); err != nil {
		tilog.Info(ctx, "req validate ", zap.Error(err))
		responseWithBadRequest(c, err)
		return
	}

	userAgent := c.Request.UserAgent()
	if len(userAgent) > 50 {
		userAgent = userAgent[:50]
	}
	clientIP := c.ClientIP()
	tilog.Info(ctx, "DeviceAuthorizationEndpoint", zap.String("clientID", req.ClientID), zap.String("clientIP", clientIP), zap.String("userAgent", userAgent),
		zap.String("forwarded-for", c.Request.Header.Get("X-Forwarded-For")), zap.String("real-ip", c.Request.Header.Get("X-Real-Ip")),
	)

	resp, err := o.oauth2Svc.HandleDeviceAuthorizationRequest(ctx, req.ClientID, clientIP, userAgent)
	if err != nil {
		c.JSON(errs.GetStatusCode(err), oauth2_dto.ErrorResponse{
			Error: err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, resp)
}
