package user_follow_author

import (
	"context"
	"server/internal/dao"
	"server/internal/model"
	"server/internal/model/do"
	"server/internal/service"
	"server/utility/ecode"

	"github.com/gogf/gf/v2/database/gdb"
)

type sUserFollowAuthor struct{}

func New() service.IUserFollowAuthor {
	return &sUserFollowAuthor{}
}
func init() {
	service.RegisterUserFollowAuthor(New())
}

// List retrieves a paginated list of user follow authors
func (s *sUserFollowAuthor) List(ctx context.Context, in *model.UserFollowAuthorListIn) (out *model.UserFollowAuthorListOut, err error) {
	out = &model.UserFollowAuthorListOut{}
	m := dao.UserFollowAuthors.Ctx(ctx)
	if in.UserId != 0 {
		m = m.Where(dao.UserFollowAuthors.Columns().UserId, in.UserId)
	}
	if in.AuthorId != 0 {
		m = m.Where(dao.UserFollowAuthors.Columns().AuthorId, in.AuthorId)
	}
	if err = m.Page(in.Page, in.Size).ScanAndCount(&out.List, &out.Total, false); err != nil {
		return
	}
	return
}

// Create adds a new user follow author
func (s *sUserFollowAuthor) Create(ctx context.Context, in *model.UserFollowAuthorAddIn) (out *model.UserFollowAuthorCRUDOut, err error) {
	err = dao.UserFollowAuthors.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		exist, err := dao.UserFollowAuthors.Ctx(ctx).TX(tx).
			Where(dao.UserFollowAuthors.Columns().UserId, in.UserId).
			Where(dao.UserFollowAuthors.Columns().AuthorId, in.AuthorId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("user_follow_author_query_failed")
		}
		if exist {
			return ecode.Params.Sub("user_follow_author_exists")
		}
		if _, err := dao.UserFollowAuthors.Ctx(ctx).TX(tx).Data(do.UserFollowAuthors{
			UserId:   in.UserId,
			AuthorId: in.AuthorId,
		}).Insert(); err != nil {
			return ecode.Fail.Sub("user_follow_author_create_failed")
		}

		// 作者被关注数 +1
		if _, err := dao.Authors.Ctx(ctx).TX(tx).
			Where(dao.Authors.Columns().Id, in.AuthorId).
			Increment(dao.Authors.Columns().FollowerCount, 1); err != nil {
			return ecode.Fail.Sub("author_follow_count_update_failed")
		}
		// 用户关注数 +1
		if _, err := dao.Users.Ctx(ctx).TX(tx).
			Where(dao.Users.Columns().Id, in.UserId).
			Increment(dao.Users.Columns().AttentionCount, 1); err != nil {
			return ecode.Fail.Sub("user_attention_count_update_failed")
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	return &model.UserFollowAuthorCRUDOut{Success: true}, nil
}

// Unfollow removes a user follow author by userId and authorId
func (s *sUserFollowAuthor) Unfollow(ctx context.Context, userId int64, authorId int64) (out *model.UserFollowAuthorCRUDOut, err error) {
	err = dao.UserFollowAuthors.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		if userId == 0 || authorId == 0 {
			return ecode.Params.Sub("user_id_or_author_id_invalid")
		}
		// 查找关注记录
		result, err := dao.UserFollowAuthors.Ctx(ctx).TX(tx).
			Where(dao.UserFollowAuthors.Columns().UserId, userId).
			Where(dao.UserFollowAuthors.Columns().AuthorId, authorId).
			Delete()
		if err != nil {
			return ecode.Fail.Sub("user_follow_author_delete_failed")
		}
		affected, err := result.RowsAffected()
		if err != nil {
			return ecode.Fail.Sub("user_follow_author_delete_failed")
		}
		if affected == 0 {
			return ecode.NotFound.Sub("user_follow_author_not_found")
		}
		// 作者被关注数 -1
		if _, err := dao.Authors.Ctx(ctx).TX(tx).
			Where(dao.Authors.Columns().Id, authorId).
			Decrement(dao.Authors.Columns().FollowerCount, 1); err != nil {
			return ecode.Fail.Sub("author_follow_count_update_failed")
		}
		// 用户关注数 -1
		if _, err := dao.Users.Ctx(ctx).TX(tx).
			Where(dao.Users.Columns().Id, userId).
			Decrement(dao.Users.Columns().AttentionCount, 1); err != nil {
			return ecode.Fail.Sub("user_attention_count_update_failed")
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return &model.UserFollowAuthorCRUDOut{Success: true}, nil
}
