package share

import (
	"net/url"
	"time"

	"github.com/labstack/echo/v4"
	"github.com/mileusna/useragent"

	"github.com/chaitin/panda-wiki/domain"
	"github.com/chaitin/panda-wiki/handler"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/usecase"
)

type ShareStatHandler struct {
	*handler.BaseHandler
	useCase *usecase.StatUseCase
	logger  *log.Logger
}

func NewShareStatHandler(baseHandler *handler.BaseHandler, echo *echo.Echo, useCase *usecase.StatUseCase, logger *log.Logger) *ShareStatHandler {
	h := &ShareStatHandler{
		BaseHandler: baseHandler,
		useCase:     useCase,
		logger:      logger.WithModule("handler.share.stat"),
	}

	group := echo.Group("/share/v1/stat")
	group.POST("/page", h.RecordPage, h.ShareAuthMiddleware.Authorize)
	return h
}

// RecordPage record page
//
//	@Summary		RecordPage
//	@Description	RecordPage
//	@Tags			share_stat
//	@Accept			json
//	@Produce		json
//	@Param			request	body		domain.StatPageReq	true	"request"
//	@Success		200		{object}	domain.Response
//	@Router			/share/v1/stat/page [post]
func (h *ShareStatHandler) RecordPage(c echo.Context) error {
	req := &domain.StatPageReq{}
	if err := c.Bind(req); err != nil {
		return h.NewResponseWithError(c, "bind request body failed", err)
	}
	if err := c.Validate(req); err != nil {
		return h.NewResponseWithError(c, "validate request body failed", err)
	}

	kbID := c.Request().Header.Get("X-KB-ID")
	// get user info --> no enterprise is nil
	var userIDValue uint
	userID := c.Get("user_id")
	if userID != nil { // can find userinfo from auth
		userIDValue = userID.(uint)
	}

	ua := c.Request().UserAgent()
	userAgent := useragent.Parse(ua)
	browserName := userAgent.Name
	browserOS := userAgent.OS
	referer := c.Request().Referer()
	refererHost := ""
	if referer != "" {
		refererURL, err := url.Parse(referer)
		if err == nil {
			refererHost = refererURL.Host
		}
	}
	sessionID := ""
	sessionIDCookie, err := c.Request().Cookie("x-pw-session-id")
	if err != nil {
		sessionID = c.Request().Header.Get("x-pw-session-id")
	} else {
		sessionID = sessionIDCookie.Value
	}
	if sessionID == "" {
		return h.NewResponseWithError(c, "session id not found", err)
	}
	ip := c.RealIP()
	stat := &domain.StatPage{
		KBID:        kbID,
		UserID:      userIDValue,
		NodeID:      req.NodeID,
		Scene:       req.Scene,
		SessionID:   sessionID,
		IP:          ip,
		UA:          ua,
		BrowserName: browserName,
		BrowserOS:   browserOS,
		Referer:     referer,
		RefererHost: refererHost,
		CreatedAt:   time.Now(),
	}
	if err := h.useCase.RecordPage(c.Request().Context(), stat); err != nil {
		return h.NewResponseWithError(c, "record page failed", err)
	}
	return h.NewResponseWithData(c, nil)
}
