<?php

namespace App\Services\User;

use App\Exceptions\AlertException;
use App\Managers\CouponManager;
use App\Models\Log\VipLogModel;
use App\Models\OrderModel;
use App\Models\User\Openid;
use App\Models\User\UserModel;
use App\Models\User\UserStateModel;
use App\Models\User\UserSysTagModel;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

/**
 * Class VipService
 * @package App\Services\User
 */
class VipService extends Service
{
    /**
     * 成为普通VIP
     * @param  int  $uid
     * @throws AlertException
     */
    public function beVip(int $uid)
    {
        if (
            !Openid::where([
            ['uid', $uid],
            ['public_id', config('wechat.fpdx.public_id')],
            ['subscribe', 1],
            ])->exists()
        ) {
            throw new AlertException("未关注", 101);
        }

        $ps = new ProfileService();
        $ps->beVip($uid, true);
    }

    /**
     * 超级VIP支付结果处理
     * @param  OrderModel  $order
     * @return bool
     * @throws \Exception
     */
    public function payment(OrderModel $order)
    {
        try {
            DB::beginTransaction();
            /** @var UserModel $user */
            $user = UserModel::findOrFail($order->uid);
            // 1. 判断要给用户增加超级会员天数
            $xuvip = false;
            $user->supvip_endat > time() && $xuvip = true;
            switch ($order->type) {
                case 12:
                    $addday = 31;
                    break;
                case 13:
                    $addday = 31 * 3;
                    $xuvip && $addday += 5;
                    break;
                case 14:
                    $addday = 31 * 12;
                    $xuvip && $addday += 31;
                    break;
                default:
                    return false;
            }
            $xuvip ? $user->supvip_endat += $addday * 86400 : $user->supvip_endat = mktime(
                0,
                0,
                0
            ) + (1 + $addday) * 86400;

            // 2. 记录kdgx_fpdx_user_record增加天数、修改到期时间
            if (UserSysTagModel::where('uid', $user->uid)->exists()) {
                $update = array('supvip_endat' => $user->supvip_endat, 'last_supvip_expire_notice_at' => 0);
                !$xuvip && $update['last_be_supvip_at'] = time();
                UserSysTagModel::where('uid', $user->uid)->increment('supvip_days', $addday, $update);
            } else {
                UserSysTagModel::create(array(
                    'uid' => $user->uid,
                    'supvip_days' => $addday,
                    'supvip_endat' => $user->supvip_endat,
                    'last_be_supvip_at' => time(),
                ));
            }

            $user->save();
            // 3. 发放72h入场券
            if (0 == UserStateModel::get($order->uid, "pay_open_supvip") || !$xuvip) {
                $couponManager = new CouponManager();
                $couponManager->generateSuperVip72FreeCoupons($user->uid);
            }
            DB::commit();
            UserStateModel::set($order->uid, "pay_open_supvip", 1);
            if ($xuvip) {
                VipLogModel::renewalSupvip($user->uid, $addday);
            } else {
                VipLogModel::openSupvip($user->uid, $addday);
            }
        } catch (\Exception $exception) {
            DB::rollBack();

            return false;
        }

        return true;
    }

    /**
     * 每期发送72小时入场券
     */
    public function send72hourTicket()
    {
        $users = UserModel::where([['supvip_endat', '>', time()]])->get();
        foreach ($users as $user) {
            $couponManager = new CouponManager();
            $couponManager->generateSuperVip72FreeCoupons($user->uid);
        }
    }

    /**
     * 内测开通超级会员通道
     * @param  int  $uid
     * @throws AlertException
     */
    public function beSuperVip(int $uid)
    {
        $exists = Redis::sismember("fpdx_supervip_test", $uid);
        if (1 == $exists) {
            $existsed = Redis::sismember("fpdx_supervip_test_ed", $uid);
            if (1 == $existsed) {
                throw new AlertException("你已经是领取了", 102);
            }
            $user = UserModel::findOrFail($uid);

            if (1 != $user->task_photo && 1 != $user->task_question) {
                throw new AlertException("请设置心动考验", 103);
            }
            // 1. 判断要给用户增加超级会员天数
            $xuvip = false;
            $user->supvip_endat > time() && $xuvip = true;
            $addday = 7;
            $xuvip ? $user->supvip_endat += $addday * 86400 : $user->supvip_endat = mktime(
                0,
                0,
                0
            ) + (1 + $addday) * 86400;

            // 2. 记录kdgx_fpdx_user_record增加天数、修改到期时间
            if (UserSysTagModel::where('uid', $user->uid)->exists()) {
                $update = array('supvip_endat' => $user->supvip_endat, 'last_supvip_expire_notice_at' => 0);
                !$xuvip && $update['last_be_supvip_at'] = mktime(0, 0, 0);
                UserSysTagModel::where('uid', $user->uid)->increment('supvip_days', $addday, $update);
            } else {
                UserSysTagModel::create(array(
                    'uid' => $user->uid,
                    'supvip_days' => $addday,
                    'supvip_endat' => $user->supvip_endat,
                    'last_be_supvip_at' => mktime(0, 0, 0),
                ));
            }
            $user->save();
            // 3. 发放72h入场券
            $couponManager = new CouponManager();
            $couponManager->generateSuperVip72FreeCoupons($user->uid);
            Redis::sadd("fpdx_supervip_test_ed", [$uid]);

            if ($xuvip) {
                VipLogModel::renewalSupvip($uid, $addday);
            } else {
                VipLogModel::openSupvip($uid, $addday);
            }
        } else {
            throw new AlertException("无内测资格", 101);
        }
    }

    /**
     * 创建卡片领取超级会员
     * @param  int  $uid
     * @throws AlertException
     */
    public function sendSuperVipByStorePartner(int $uid)
    {
        $existsed = Redis::sismember("fpdx:supervip:send:store:partner", $uid);
        if (1 == $existsed) {
            throw new AlertException("你已经是领取了", 200);
        }
        $user = UserModel::findOrFail($uid);

        // 1. 判断要给用户增加超级会员天数
        $xuvip = false;
        $user->supvip_endat > time() && $xuvip = true;
        $addday = 7;
        $xuvip ? $user->supvip_endat += $addday * 86400 : $user->supvip_endat = mktime(0, 0, 0) + (1 + $addday) * 86400;

        // 2. 记录kdgx_fpdx_user_record增加天数、修改到期时间
        if (UserSysTagModel::where('uid', $user->uid)->exists()) {
            $update = array('supvip_endat' => $user->supvip_endat, 'last_supvip_expire_notice_at' => 0);
            !$xuvip && $update['last_be_supvip_at'] = mktime(0, 0, 0);
            UserSysTagModel::where('uid', $user->uid)->increment('supvip_days', $addday, $update);
        } else {
            UserSysTagModel::create(array(
                'uid' => $user->uid,
                'supvip_days' => $addday,
                'supvip_endat' => $user->supvip_endat,
                'last_be_supvip_at' => mktime(0, 0, 0),
            ));
        }
        $user->save();
        // 3. 发放72h入场券
        $couponManager = new CouponManager();
        $couponManager->generateSuperVip72FreeCoupons($user->uid);

        Redis::sadd("fpdx:supervip:send:store:partner", [$uid]);

        if ($xuvip) {
            VipLogModel::renewalSupvip($uid, $addday);
        } else {
            VipLogModel::openSupvip($uid, $addday);
        }
    }

    /**
     * 每月提醒会员到期
     * 是否到期提醒过
     */
    public function remindExpire()
    {
        // 是否到期提醒过
        // 明天0点时间 < 到期时间 < 后天0点时间
        $tags = UserSysTagModel::whereBetween(
            'supvip_endat',
            [mktime(0, 0, 0) + 86410, mktime(0, 0, 0) + 86400 * 2]
        )->where(
            'last_supvip_expire_notice_at',
            0
        )->limit(10)->get();
        $ns = new NoticeService();
        foreach ($tags as $tag) {
            if ($ns->supvipExpire($tag->uid)) {
                UserSysTagModel::where('uid', $tag->uid)->update(['last_supvip_expire_notice_at' => time()]);
            }
        }
    }
}
