package user_sign_in_logs

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 sUserSignInLogs struct{}

func New() service.IUserSignInLogs {
	return &sUserSignInLogs{}
}
func init() {
	service.RegisterUserSignInLogs(New())
}

// Sign 用户签到，只允许每日唯一签到
func (s *sUserSignInLogs) Sign(ctx context.Context, in *model.UserSignInLogSignIn) (*model.UserSignInLogSignOut, error) {
	// 事务前查询奖励明细
	detail, err := dao.SignInRewardDetails.Ctx(ctx).Where(do.SignInRewardDetails{Id: in.RewardDetailId}).One()
	if err != nil {
		return nil, ecode.New(10014, "sign_in_reward_detail_query_failed")
	}
	if detail == nil || detail.IsEmpty() {
		return nil, ecode.New(10015, "sign_in_reward_detail_not_found")
	}
	quantity := detail["quantity"].Int()

	var success bool
	err = dao.UserSignInLogs.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 检查是否已签到
		count, err := dao.UserSignInLogs.Ctx(ctx).TX(tx).Where(do.UserSignInLogs{
			UserId:     in.UserId,
			RuleId:     in.RuleId,
			SignInDate: in.SignInDate,
			DeletedAt:  nil,
		}).Count()
		if err != nil {
			return ecode.New(10010, "user_sign_in_log_query_failed")
		}
		if count > 0 {
			success = false
			return nil
		}
		// 插入签到记录
		result, err := dao.UserSignInLogs.Ctx(ctx).TX(tx).Data(do.UserSignInLogs{
			UserId:         in.UserId,
			RuleId:         in.RuleId,
			RewardDetailId: in.RewardDetailId,
			SignInDate:     in.SignInDate,
			Quantity:       quantity,
			Status:         1,
		}).InsertAndGetId()
		if err != nil {
			return ecode.New(10011, "user_sign_in_log_create_failed")
		}
		// 插入积分日志
		_, err = dao.UserPointsLogs.Ctx(ctx).TX(tx).Data(do.UserPointsLogs{
			UserId:         in.UserId,
			ChangeType:     2, // 2=收入(earn)
			PointsChange:   quantity,
			RelatedOrderId: result,
			Description:    "签到奖励",
		}).Insert()
		if err != nil {
			return ecode.New(10012, "user_points_log_create_failed")
		}
		// 更新用户积分
		_, err = dao.Users.Ctx(ctx).TX(tx).Where(do.Users{Id: in.UserId}).Increment("points", quantity)
		if err != nil {
			return ecode.New(10013, "user_points_update_failed")
		}
		success = true
		return nil
	})
	if err != nil {
		return nil, err
	}
	return &model.UserSignInLogSignOut{Success: success}, nil
}
