<?php

namespace App\Modules\User\Services;

use App\Modules\User\Models\User;
use Illuminate\Support\Facades\DB;
use Redis;

/**
 * @property int $this->uid;
 * @property int $reward_list;
 */
class SignService
{
    protected $uid;

    protected $reward_list = [30, 35, 40, 45, 50, 55, 60];

    public function __construct(int $uid)
    {
        $this->uid = $uid;
    }

    protected function setRewardList(array $data)
    {
        $this->reward_list = $data;
    }

    /**
     * 用户签到
     */
    public function sign()
    {
        $date = $this->getSignDate();
        $sign_day = $this->getSignDay();
        if (!$date || $date != date('Y-m-d')) {
            $reward = $this->getRewardCoin($sign_day);
            $this->saveReward($reward);
            $this->saveRewardInfoInRedis($reward, $sign_day);
            $this->addSignDay();
        }
    }

    /**
     * 获取用户签到信息
     */
    public function getSignInfo()
    {
        $date = $this->getSignDate();
        $is_sign = $date == date('Y-m-d');
        $sign_day = $this->getSignDay();
        $reward_list = $this->reward_list;
        return compact('is_sign', 'sign_day', 'reward_list');
    }

    /**
     * 保存奖励金额
     * @param int $reward 签到奖励书币
     */
    private function saveReward(int $reward)
    {
        User::where('id', $this->uid)->update([
            'balance' => DB::raw('balance+' . $reward),
            'reward_balance' => DB::raw('reward_balance+' . $reward)
        ]);
    }

    /**
     * 保存签到信息到redis
     * @param int $reward 签到奖励书币
     * @param int $sign_day 签到天数
     */
    private function saveRewardInfoInRedis(int $reward, int $sign_day)
    {
        $sign_data = [
            'uid' => $this->uid,
            'price' => $reward,
            'day' => $sign_day,
            'sign_time' => time(),
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ];
        Redis::sadd('user_sign:uid', $this->uid);
        Redis::hset('user_sign:uid:info', $this->uid, json_encode($sign_data));
        Redis::hset('book_read:' . $this->uid, 'sign_info', json_encode($sign_data));
    }

    /**
     * 获取用户签到日期
     * @return string|bool
     */
    private function getSignDate()
    {
        $sign_date = Redis::hget('book_read:' . $this->uid, 'sign_day');
        if ($sign_date && ($sign_date == date('Y-m-d', time() - 86400) || $sign_date == date('Y-m-d'))) {
            return $sign_date;
        } else {
            $this->delSignDay();
            return false;
        }
    }

    /**
     * 获取用户签到天数
     * @return int|bool
     */
    private function getSignDay()
    {
        $sign_day =  Redis::hget('book_read:' . $this->uid, 'sign_counts');
        return $sign_day ? (int)$sign_day : 0;
    }

    /**
     * 增加签到
     * @return int
     */
    private function addSignDay()
    {
        Redis::hset('book_read:' . $this->uid, 'sign_day', date('Y-m-d'));
        return Redis::hincrby('book_read:' . $this->uid, 'sign_counts', 1);
    }

    /**
     * 重置签到天数
     */
    private function delSignDay()
    {
        return Redis::hDel('book_read:' . $this->uid, 'sign_counts');
    }

    /**
     * 获取签到奖励金额
     * @param int $sign_day 签到天数
     * @return int 
     */
    private function getRewardCoin(int $sign_day)
    {
        return $this->reward_list[$sign_day % 7];
    }
}
