// Code generated by hertz generator.

package core

import (
	"common/kitex_gen/douyin/rpc"
	"common/utils"
	"context"

	core "gateway/biz/model/douyin/core"
	"gateway/internal/cache"
	"gateway/internal/db"
	"gateway/internal/jwt"
	"gateway/internal/services"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/protocol/consts"
)

// Favorite .
// @router /douyin/favorite/action/ [POST]
func Favorite(ctx context.Context, c *app.RequestContext) {
	var err error
	var req core.DouyinFavoriteActionRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		utils.InvalidInput(c, err)
		return
	}

	user, err := jwt.AuthorizedUser(c, &req.Token)
	if err != nil || user == 0 {
		utils.ErrorUnauthorized.Write(c)
		return
	}

	if cache.FavoriteLimit.Wait(ctx, user) != nil {
		utils.ErrorTooManyRequests.Write(c)
		return
	}

	if err := hasVideo(ctx, req.VideoId); err != utils.ErrorOk {
		err.Write(c)
		return
	}

	r, err := services.Reaction.Favorite(ctx, &rpc.DouyinFavoriteActionRequest{
		RequestUserId: user,
		VideoId:       req.VideoId,
		ActionType:    req.ActionType,
	})
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}
	if utils.RpcError(c, r.StatusCode) {
		return
	}

	resp := new(core.DouyinFavoriteActionResponse)

	c.JSON(consts.StatusOK, resp)
}

// ListFavorites .
// @router /douyin/favorite/list/ [GET]
func ListFavorites(ctx context.Context, c *app.RequestContext) {
	var err error
	var req core.DouyinFavoriteListRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		utils.InvalidInput(c, err)
		return
	}

	user, err := jwt.AuthorizedUser(c, &req.Token)
	if err != nil || user == 0 {
		utils.ErrorUnauthorized.Write(c)
		return
	}

	if !db.UserExists(req.UserId) {
		utils.ErrorNoSuchUser.Write(c)
		return
	}

	r, err := services.Reaction.ListFavorites(ctx, &rpc.DouyinFavoriteListRequest{
		UserId:        req.UserId,
		RequestUserId: user,
	})
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}
	if utils.RpcError(c, r.StatusCode) {
		return
	}

	info, err := services.Feed.VideoInfo(ctx, &rpc.VideoBatchInfoRequest{
		VideoIds:      r.VideoList,
		RequestUserId: user,
	})
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}
	if utils.RpcError(c, r.StatusCode) {
		return
	}

	resp := new(core.DouyinFavoriteListResponse)
	resp.VideoList, err = generateVideoList(ctx, info.Videos)
	if err != nil {
		utils.Error(c, err)
		return
	}
	for _, v := range resp.VideoList {
		v.IsFavorite = true
	}

	c.JSON(consts.StatusOK, resp)
}

func hasVideo(ctx context.Context, id int64) utils.ErrorCode {
	r, err := services.Feed.VideoInfo(ctx, &rpc.VideoBatchInfoRequest{
		VideoIds:      []int64{id},
		RequestUserId: 0,
	})
	if err != nil {
		return utils.ErrorRpcTimeout
	}
	if len(r.Videos) == 1 {
		return utils.ErrorOk
	} else {
		return utils.ErrorWrongParameter
	}
}

// Comment .
// @router /douyin/comment/action/ [POST]
func Comment(ctx context.Context, c *app.RequestContext) {
	var err error
	var req core.DouyinCommentActionRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		utils.InvalidInput(c, err)
		return
	}

	id, err := jwt.AuthorizedUser(c, &req.Token)
	if err != nil || id == 0 {
		utils.Error(c, err)
		return
	}

	if err := hasVideo(ctx, req.VideoId); err != utils.ErrorOk {
		err.Write(c)
		return
	}

	r, err := services.Reaction.Comment(ctx, &rpc.DouyinCommentActionRequest{
		RequestUserId: id,
		VideoId:       req.VideoId,
		ActionType:    req.ActionType,
		CommentText:   req.CommentText,
		CommentId:     req.CommentId,
	})
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}
	if utils.RpcError(c, r.StatusCode) {
		return
	}

	resp := new(core.DouyinCommentActionResponse)
	if r.Comment != nil {
		user, err := db.FindUserById(r.Comment.User.Id)
		if err != nil {
			utils.Error(c, err)
			return
		}
		resp.Comment = &core.Comment{
			Id:         r.Comment.Id,
			User:       services.FromUser(user, false),
			Content:    r.Comment.Content,
			CreateDate: r.Comment.CreateDate,
		}
	}

	c.JSON(consts.StatusOK, resp)
}

// ListComments .
// @router /douyin/comment/list/ [GET]
func ListComments(ctx context.Context, c *app.RequestContext) {
	var err error
	var req core.DouyinCommentListRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		utils.InvalidInput(c, err)
		return
	}

	user, err := jwt.AuthorizedUser(c, &req.Token)
	if err != nil {
		user = 0
	}

	r, err := services.Reaction.ListComments(ctx, &rpc.DouyinCommentListRequest{
		RequestUserId: user,
		VideoId:       req.VideoId,
	})
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}
	if utils.RpcError(c, r.StatusCode) {
		return
	}

	rpcAuthors := make([]*rpc.User, 0, len(r.CommentList))
	for _, comment := range r.CommentList {
		rpcAuthors = append(rpcAuthors, comment.User)
	}
	authors, err := services.GatherUserInfo(ctx, user, rpcAuthors, true, true)
	if err != nil {
		utils.ErrorRpcTimeout.Write(c)
		return
	}

	resp := new(core.DouyinCommentListResponse)
	comments := make([]*core.Comment, 0, len(r.CommentList))
	for _, comment := range r.CommentList {
		comments = append(comments, &core.Comment{
			Id:         comment.Id,
			User:       authors[comment.User.Id],
			Content:    comment.Content,
			CreateDate: comment.CreateDate,
		})
	}
	resp.CommentList = comments

	c.JSON(consts.StatusOK, resp)
}
