<?php

namespace App\Services\User;

use App\Exceptions\AlertException;
use App\Jobs\GrowingIO\SignFlowerReportJob;
use App\Jobs\GrowingIO\SignReportJob;
use App\Managers\CouponManager;
use App\Models\FlowerLogModel;
use App\Models\Log\SignRewardLogModel;
use App\Models\User\SignModel;
use App\Models\User\UserModel;
use App\Models\User\UserStateModel;
use App\Services\Service;
use Illuminate\Contracts\Cache\LockTimeoutException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * 签到-领奖励
 * Class SignService
 * @package App\Services\User
 */
class SignService extends Service
{

    public static $SIGN = array(
        1 => [
            "is_big_reward" => 0,
            "reward" => ['flower', 'popularity', 'app_lock'],
        ],
        2 => [
            "is_big_reward" => 0,
            "reward" => ['flower', 'popularity', 'app_lock'],
        ],
        3 => [
            "is_big_reward" => 1,
            "reward" => ['flower', 'popularity', 'app_lock', 'couponsvip'] // 超级会员满减券抵扣9元
        ],
        4 => [
            "is_big_reward" => 0,
            "reward" => ['flower', 'popularity', 'app_lock'],
        ],
        5 => [
            "is_big_reward" => 1,
            "reward" => ['flower', 'popularity', 'app_lock', 'coupon72dis'] // 72小时折扣券
        ],
        6 => [
            "is_big_reward" => 0,
            "reward" => ['flower', 'popularity', 'app_lock'],
        ],
        7 => [
            "is_big_reward" => 1,
            "reward" => ['flower', 'popularity', 'app_lock', 'coupon72pair'] // 72小时报名券
        ],
    );

    /**
     * 今日签到情况
     * @param  int  $uid
     * @return array
     */
    public function today(int $uid): array
    {
        $be_continuous_day = 0;     // 连续签到几天
        $is_big_reward = 0;         // 是否有礼包
        $is_sign = false;           // 今日是否签到
        $arrReward = array();       // 签到奖励
        try {
            $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
            if ($sign->sign_at->isToday()) {
                $is_sign = true;
                $be_continuous_day = $sign->be_continuous_day;
                $is_big_reward = self::$SIGN[$be_continuous_day]['is_big_reward'];
                foreach (self::$SIGN[$be_continuous_day]['reward'] as $reward) {
                    if (
                        SignRewardLogModel::where([['uid', $uid], ['reward', $reward]])
                        ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
                    ) {
                        $arrReward[$reward] = true;
                    } else {
                        $arrReward[$reward] = false;
                    }
                }
            } elseif ($sign->sign_at->isYesterday()) {
                $be_continuous_day = $sign->be_continuous_day;
                $is_big_reward = self::$SIGN[($be_continuous_day % 7) + 1]['is_big_reward'];
                if (7 == $be_continuous_day) {
                    $be_continuous_day = 0;
                }
            }
        } catch (ModelNotFoundException $exception) {
            $be_continuous_day = 0;
        }

        return array(
            'be_continuous_day' => $be_continuous_day,
            'is_big_reward' => $is_big_reward,
            'is_sign' => $is_sign,
            'reward' => $arrReward,
        );
    }

    /**
     * 签到
     * @param  int  $uid
     * @param $platform
     * @return bool
     * @throws AlertException
     */
    public function sign(int $uid, $platform): bool
    {
        $be_continuous_day = 1;    // 连续签到几天
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->first();
        if (collect($sign)->isNotEmpty()) {
            if ($sign->sign_at->isToday()) {
                throw new AlertException("已经签到了");
            } elseif ($sign->sign_at->isYesterday()) {
                $be_continuous_day = $sign->be_continuous_day % 7 + 1;
            }
        }

        $lock = Cache::lock("sign:{$uid}", 60);
        try {
            $lock->get(function () use ($uid, $be_continuous_day, $platform) {
                $sign = SignModel::create([
                    'uid' => $uid,
                    'be_continuous_day' => $be_continuous_day,
                    'sign_date' => date('Y-m-d'),
                ]);

                dispatch_now(new SignReportJob($sign, $platform));
            });
        } catch (LockTimeoutException $exception) {
        } finally {
            optional($lock)->release();
        }

        return true;
    }

    /**
     * 领取小花奖励
     * @param  int  $uid
     * @return float|int|string
     * @throws AlertException*@throws \Exception
     * @throws \Exception
     */
    public function rewardFlower(int $uid)
    {
        if (
            SignRewardLogModel::where([['uid', $uid], ['reward', 'flower']])
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
        ) {
            throw new AlertException("已领取过");
        }
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
        if ($sign->sign_at->isToday()) {
            if (!in_array("flower", self::$SIGN[$sign->be_continuous_day]['reward'])) {
                throw new AlertException("无这个奖励");
            }
            $rdCnt = sprintf("%.2f", 1.0 + mt_rand() / mt_getrandmax() * (3.0 - 1.0));
            $rdCnt = (self::$SIGN[$sign->be_continuous_day]['is_big_reward'] + 1) * $rdCnt;
            try {
                DB::beginTransaction();
                SignRewardLogModel::create([
                    'uid' => $uid,
                    'reward' => 'flower',
                    'data' => $rdCnt,
                ]);
                $user = UserModel::where('uid', $uid)->first();
                if ($user) {
                    $user->increment("red_flower", $rdCnt);
                }
                $flowerLog = FlowerLogModel::create([
                    'uid' => $uid,
                    'type' => 7,
                    'red_flower' => $rdCnt,
                    'remark' => '签到奖励',
                ]);
                dispatch_now(new SignFlowerReportJob($flowerLog, $user));
                DB::commit();

                return $rdCnt;
            } catch (\Exception $exception) {
                DB::rollBack();
                throw $exception;
            }
        } else {
            throw new AlertException("还未签到签到了");
        }
    }

    /**
     * 领取人气值奖励
     * @param  int  $uid
     * @return float|int|string
     * @throws AlertException
     */
    public function rewardPopularity(int $uid)
    {
        if (
            SignRewardLogModel::where('uid', $uid)
            ->where('reward', 'popularity')
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())
            ->exists()
        ) {
            throw new AlertException("已领取过");
        }
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
        if ($sign->sign_at->isToday()) {
            if (!in_array("popularity", self::$SIGN[$sign->be_continuous_day]['reward'])) {
                throw new AlertException("无这个奖励");
            }
            $long = (self::$SIGN[$sign->be_continuous_day]['is_big_reward'] + 1) * 5 * 3600;
            try {
                DB::beginTransaction();
                SignRewardLogModel::create([
                    'uid' => $uid,
                    'reward' => 'popularity',
                    'data' => $long,
                ]);
                UserStateModel::inc($uid, "popularity_sign_end_at", $long, true);
                DB::commit();

                return intval($long / 3600);
            } catch (\Exception $exception) {
                DB::rollBack();
                throw $exception;
            }
        } else {
            throw new AlertException("还未签到签到了");
        }
    }

    /**
     * 领取解锁次数
     * @param  int  $uid
     * @throws AlertException
     */
    public function rewardUnLookCard(int $uid)
    {
        if (!$this->isSign($uid)) {
            throw new AlertException("还未签到");
        }

        if (
            SignRewardLogModel::where([['uid', $uid], ['reward', 'app_lock']])
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
        ) {
            throw new AlertException("已领取过");
        }

        SignRewardLogModel::create([
            'uid' => $uid,
            'reward' => 'app_lock',
            'data' => 1,
        ]);

        UserModel::where('uid', $uid)->increment('app_like_unlock_count');
    }

    /**
     * 判断是否签到
     * @param $uid
     * @return mixed
     */
    public function isSign($uid)
    {
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();

        return $sign->sign_at->isToday();
    }

    /**
     * 领取72h卡券满减券
     * @param  int  $uid
     * @return float|int|string
     * @throws AlertException
     */
    public function rewardCouponSuperVip(int $uid)
    {
        if (
            SignRewardLogModel::where([['uid', $uid], ['reward', 'couponsvip']])
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
        ) {
            throw new AlertException("已领取过");
        }
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
        if ($sign->sign_at->isToday()) {
            if (!in_array("couponsvip", self::$SIGN[$sign->be_continuous_day]['reward'])) {
                throw new AlertException("无这个奖励");
            }
            DB::beginTransaction();
            try {
                SignRewardLogModel::create([
                    'uid' => $uid,
                    'reward' => 'couponsvip',
                    'data' => 1,
                ]);

                $couponManager = new CouponManager();
                $couponManager->generateSignSuperVipCoupons($uid);

                DB::commit();
            } catch (\Exception $exception) {
                DB::rollBack();
                throw $exception;
            }

            return 1;
        } else {
            throw new AlertException("还未签到签到了");
        }
    }

    /**
     * 72小时折扣券
     * @param  int  $uid
     * @return float|int|string
     * @throws AlertException
     */
    public function rewardCoupon72Dis(int $uid)
    {
        if (
            SignRewardLogModel::where([['uid', $uid], ['reward', 'coupon72dis']])
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
        ) {
            throw new AlertException("已领取过");
        }
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
        if ($sign->sign_at->isToday()) {
            if (!in_array("coupon72dis", self::$SIGN[$sign->be_continuous_day]['reward'])) {
                throw new AlertException("无这个奖励");
            }
            DB::beginTransaction();
            try {
                SignRewardLogModel::create([
                    'uid' => $uid,
                    'reward' => 'coupon72dis',
                    'data' => 1,
                ]);

                $couponManager = new CouponManager();
                $couponManager->generateSign72DiscountCoupons($uid);

                DB::commit();
            } catch (\Exception $exception) {
                DB::rollBack();
                throw $exception;
            }

            return 1;
        } else {
            throw new AlertException("还未签到签到了");
        }
    }

    /**
     * 72小时入场券
     * @param  int  $uid
     * @return float|int|string
     * @throws AlertException
     */
    public function rewardCoupon72Pair(int $uid)
    {
        if (
            SignRewardLogModel::where([['uid', $uid], ['reward', 'coupon72pair']])
            ->where('created_at', '>', Carbon::today()->toDateTimeLocalString())->exists()
        ) {
            throw new AlertException("已领取过");
        }
        $sign = SignModel::where("uid", $uid)->orderBy("id", 'desc')->firstOrFail();
        if ($sign->sign_at->isToday()) {
            if (!in_array("coupon72pair", self::$SIGN[$sign->be_continuous_day]['reward'])) {
                throw new AlertException("无这个奖励");
            }
            DB::beginTransaction();
            try {
                SignRewardLogModel::create([
                    'uid' => $uid,
                    'reward' => 'coupon72pair',
                    'data' => 1,
                ]);
                $couponManager = new CouponManager();
                $couponManager->generateSuperVip72FreeCoupons($uid);
                DB::commit();
            } catch (\Exception $exception) {
                DB::rollBack();
                throw $exception;
            }

            return 1;
        } else {
            throw new AlertException("还未签到签到了");
        }
    }
}
