<?php

namespace App\Services\Deed;

use App\Exceptions\ApiException;
use App\Jobs\NoticeJob;
use App\Models\Common\NoticeManageModel;
use App\Models\Deed\InvitationCardModel;
use App\Models\Deed\NoticeReadModel;
use App\Models\Log\FeedLogModel;
use App\Models\NoticeModel;
use App\Models\PraiseModel;
use App\Models\User\UserModel;
use App\Services\Log\NoticeLogService;
use App\Services\Notice\ManageService;
use App\Services\Service;
use Illuminate\Support\Facades\Redis;
use PocketBE\MsyPush\Jobs\RegistEventJob;

class NoticeService extends Service
{

    /**
     * 重置未读次数
     * @param $uid
     */
    public function readNotice($uid)
    {
        NoticeReadModel::updateOrCreate(
            ['uid' => $uid],
            ['unread_cnt' => 0]
        );
    }


    /**
     * 订阅开关
     * @param  int  $uid
     * @return float|int
     */
    public function subscribe(int $uid)
    {
        $profile = NoticeManageModel::firstOrCreate([
            'uid' => $uid,
            'key' => 'flipped_notice',
        ], [
            'group' => 'flipped',
            'isopen' => 0,
        ]);
        $profile->isopen = abs($profile->isopen - 1);
        $profile->save();

        return $profile->isopen;
    }

    /**
     * 心动邀请通知延迟
     */
    public function invitationDelay()
    {
        $json = Redis::lpop("{fpdx:invitation:notice:dely}");
        while (!empty($json)) {
            try {
                $data = json_decode($json, true);
                $this->invitation($data['uid'], $data['invite_uid'], $data['invite_id'], $data['question_type'], true);
                $json = Redis::lpop("{fpdx:invitation:notice:dely}");
                sleep(rand(10, 300));
            } catch (\Exception $exception) {
            }
        }
    }

    /**
     * 发送申请通知
     * @param  int  $uid  触发用户
     * @param  int  $invite_uid  通知用户
     * @param  int  $invite_id  邀请id
     * @param  int  $question_type
     * @param  bool  $is_callback  是否作为回调函数
     * @return bool
     * @throws ApiException
     * @throws \App\Exceptions\AlertException
     */
    public function invitation($uid, $invite_uid, $invite_id, $question_type, $is_callback = true)
    {
        $title = "心动邀请通知";
        $uuid = uuid();
        $noticeLog = new NoticeLogService();
        $to_uid = $invite_uid;

        // 系统通知 type=13
        NoticeModel::create([
            'uid' => $to_uid,
            'type' => 13,
            'title' => "收到新的好友申请",
            'content' => "收到1条新的好友申请",
        ]);

        // 通知开关
        $nms = new ManageService();
        if (!$nms->getNoticeByKey($to_uid, "flipped_notice")) {
            $noticeLog->record($to_uid, $title, "取消订阅", $uuid);

            return false;
        }

        if (time() < mktime(8, 0, 0) || time() > mktime(23, 0, 0)) {
            // 延迟发送
            Redis::rpush("{fpdx:invitation:notice:dely}", [
                json_encode([
                    'uid' => $uid,
                    'invite_uid' => $invite_uid,
                    'invite_id' => $invite_id,
                    'question_type' => $question_type,
                ]),
            ]);

            return true;
        }

        /** @var UserModel $user */
        $user = UserModel::findOrFail($uid);
        /** @var UserModel $to_user */
        $to_user = UserModel::findOrFail($to_uid);

        // 三天内访问次数
        $visitor_count = FeedLogModel::where([
            ['partner_id', $to_user->partner_id],
            ['created_at', '>', strtotime("-3 day")],
        ])->count();
        // 三天内的点赞次数
        $praise_count = PraiseModel::where([
            ['partner_id', $to_user->partner_id],
            ['created_at', '>', strtotime("-3 day")],
        ])->count();

        $invite_count = InvitationCardModel::where([
            ['invite_uid', $to_user->uid],
            ['created_at', '>', strtotime("-3 day")],
        ])->count();

        $description = "在过去的3天里";
        $description .= $visitor_count ? "共有{$visitor_count}个访客访问了你" : "";
        $description .= $praise_count ? ",收到{$praise_count}个「心动」" : "";
        $description .= $invite_count ? ",收到{$invite_count}个「好友申请」" : "";
        $description .= "。";
        // 通知队列
        $payload = [
            'to_user' => $to_user->getAuth(),
            'user' => $to_user->toArray(),
            'from_user' => $user->toArray(),
            'meta' => [
                'visitor_count' => $visitor_count,
                'praise_count' => $praise_count,
                'invite_count' => $invite_count,
                'description' => $description,
                'date' => date('Y-m-d'),
                'datetime' => date('Y-m-d H:i:s'),
            ],
        ];

        if ($is_callback) {
            // QQ通知事件
            dispatch(new RegistEventJob(100013, $payload))->onQueue("{push}");
            NoticeJob::dispatch(
                $to_uid,
                array(new self(), __FUNCTION__),
                array($uid, $to_uid, $invite_id, $question_type)
            );

            return true;
        }

        // 通知事件
        dispatch(new RegistEventJob(100002, $payload))->onQueue("{push}");

        return true;
    }

    /**
     * 好友申请成功提醒
     * @param  int  $to_uid  邀请者|发送者
     * @param  int  $be_uid  被邀请者
     * @return bool
     */
    public function invitationSuccess($to_uid, $be_uid)
    {

        // 通知队列
        $to_user = UserModel::find($to_uid);
        $be_user = UserModel::find($be_uid);
        $payload = [
            'to_user' => $to_user->getAuth(),
            'user' => $to_user->toArray(),
            'be_user' => $be_user->toArray(),
            'meta' => [
                'date' => date('Y-m-d'),
            ],
        ];
        dispatch(new RegistEventJob(100003, $payload))->onQueue("{push}");
    }


    /**
     * 相互心动通知
     * @param  int  $to_uid
     * @param  int  $be_uid
     * @return bool
     */
    public function eachLike(int $to_uid, int $be_uid)
    {
        /** @var UserModel $user */
        $user = UserModel::findOrFail($to_uid);
        $be_user = UserModel::findOrFail($be_uid);

        // 通知队列
        $payload = [
            'to_user' => $user->getAuth(),
            'user' => $user->toArray(),
            'be_user' => $be_user->toArray(),
            'meta' => [
                'date' => date('Y-m-d'),
            ],
        ];
        dispatch(new RegistEventJob(100004, $payload))->onQueue("{push}");
    }
}
