<?php

namespace App\Services\Deed;

use App\Exceptions\AlertException;
use App\Models\Deed\FriendsModel;
use App\Models\Deed\InvitationCardModel;
use App\Models\PartnerModel;
use App\Models\PraiseModel;
use App\Models\User\LikeInviteQuestionModel;
use App\Models\User\SuperLikeModel;
use App\Models\User\UserModel;
use App\Services\Service;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

class InvitationService extends Service
{
    public const GOOD = array(
        'flower' => 1,
    );

    public function pay(int $uid, int $invite_uid, int $type)
    {
        if (false && 6 <= InvitationCardModel::where([['uid', $uid], ['invite_uid', $invite_uid]])->count()) {
            throw new AlertException("已达邀请上限", 102);
        }

        $user = UserModel::findOrFail($uid);
        if (1 > $user->red_flower) {
            throw new AlertException("小花不够", 101);
        }

        $user->decrement("red_flower", 1);
        DB::table('kdgx_partner_charge_pay_logs')->insert([
            'uid' => $uid,
            'create_at' => time(),
            'type' => 14,
            'red_flower' => 0 - 1,
            'gold_flower' => 0,
            'remark' => "心动邀请",
        ]);

        return true;
    }

    /**
     * 创建一个邀请
     * @param  int  $uid
     * @param  int  $invite_uid
     * @param  int  $question_type
     * @param  array  $question
     * @param $say_hello
     * @param  array  $request
     * @param $kk
     * @return mixed
     * @throws AlertException
     */
    public function create(
        int $uid,
        int $invite_uid,
        int $question_type,
        array $question,
        $say_hello,
        $paint_id,
        $request_content,
        $kk
    ) {
        if ($uid == $invite_uid) {
            throw new AlertException("不能邀请自己参加活动哦", 422);
        }


        $user = UserModel::findOrFail($uid);
        $incardmodel = new InvitationCardModel();

        $expired_at = time() + 86400 * 2;
        $fill = array(
            'uid' => $uid,
            'invite_uid' => $invite_uid,
            'kk' => $kk,
            'type' => 0,
            'expired_at' => $expired_at,
            'say_hello' => $say_hello,
            'paint_id' => $paint_id,
            'request_content' => $request_content,
        );
        if (0 != $question_type) {
            $fill['question_id'] = $question['question_id'];
            $fill['question_answer'] = $question['question_answer'];
            $fill['question_type'] = $question_type;
        }
        $invite = $incardmodel->fill($fill);
        $invite->save();
        try {
            $ns = new \App\Services\Deed\NoticeService();
            $ns->invitation($uid, $invite_uid, $invite->id, $question_type, true);
        } catch (\Exception $exception) {
        }

        return $invite->id;
    }

    /**
     * 通过id获取邀请信息
     * @param  int  $uid
     * @param  int  $invitation_id
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model
     */
    public function getById(int $uid, int $invitation_id)
    {
        $icm = new InvitationCardModel();
        $data = InvitationCardModel::findOrFail($invitation_id);
        $data->task_question_answer = json_decode($data->task_question_answer, true);
        $question = LikeInviteQuestionModel::withTrashed()->find($data->question_id);
        if ($question) {
            $question->question = $question ? json_decode($question->question, true) : null;
        }
        $data->question = $question;
        if ($data->uid == $uid) {
            $iuid = $data->invite_uid;
        } else {
            $iuid = $data->uid;
        }
        $partner = PartnerModel::where('uid', $iuid)->first();
        if (collect($partner)->isEmpty()) {
            $partner = null;
        } else {
            $user = UserModel::findOrFail($partner->uid, [
                'uid',
                'headimgurl',
                'nickname',
                'age',
                'star',
                'introduce',
                'expect',
                'height',
                'sex',
                'school',
                'address',
                'home',
                'tag_1',
                'tag_2',
                'tag_3',
                'tag_4',
                'weixin',
                'qq',
                'supvip_endat',
            ]);
            $user->invite_cnt = $icm->where('invite_uid', $iuid)->count();
            $partner->setAttribute("user", $user);

            // 与self的关系处理
            $self = array(
                'friend' => false,
                'praise' => false,
                'invite' => false,
                'superlike' => false,
            );
            $friend = FriendsModel::where([['uid', $uid], ['friend_uid', $partner->uid]])->first();

            $self['friend'] = $friend;
            if (PraiseModel::where([['uid', $uid], ['partner_id', $partner->id], ['type', 1]])->exists()) {
                $self['praise'] = true;
            }
            $invite = InvitationCardModel::where([
                ['uid', $uid],
                ['invite_uid', $partner->uid],
                ['expired_at', '>', time()],
            ])->groupBy('question_type')->get(['question_type'])->pluck('question_type');
            $self['invite'] = $invite;
            if (SuperLikeModel::where([['uid', $uid], ['partner_id', $partner->id]])->exists()) {
                $self['superlike'] = true;
            }
            $partner->setAttribute("self", $self);
        }
        $data->partner = $partner;

        return $data;
    }

    /**
     * 接收到的待处理邀请
     * @param  int  $uid
     * @param  array  $pages
     * @return array
     */
    public function receivesByUnhandle(int $uid, array $pages)
    {
        $icm = new InvitationCardModel();

        $total = $icm->where(array(
            ['invite_uid', $uid],
            ['state', 0],
            ['read', 0],
            ['expired_at', '>', time()],
        ))->count();
        $datas = $icm->where(array(['invite_uid', $uid], ['state', 0], ['read', 0], ['expired_at', '>', time()]))
            ->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])->orderBy('id', 'desc')->get();

        $users = UserModel::whereIn('uid', $datas->pluck('uid')->toArray())->get([
            'uid',
            'headimgurl',
            'nickname',
            'partner_id',
            'age',
            'star',
            'introduce',
            'expect',
            'height',
            'sex',
            'school',
            'address',
            'home',
            'tag_1',
            'tag_2',
            'tag_3',
            'tag_4',
            'wx_auth',
            'identity_auth',
            'supvip_endat',
        ])->toArray();
        $users = array_combine(array_column($users, 'uid'), $users);
        $partners = PartnerModel::whereIn('id', array_column($users, 'partner_id'))->get()->toArray();
        $partners = array_combine(array_column($partners, 'id'), $partners);

        $result = array();
        $index_uid = array();
        $i = 0;

        foreach ($datas as $data) {
            try {
                $data = $invite = $data->toArray();
                $duid = $data['uid'];
                if (!isset($index_uid[$duid])) {
                    $index_uid[$duid] = $i;
                    $data['invites'][] = $invite;
                    $user = $users[$duid];
                    $user['invite_cnt'] = $icm->where('invite_uid', $duid)->count();
                    $partner = $partners[$user['partner_id']];
                    $partner['user'] = $user;
                    $data['partner'] = $partner;
                    $result[$i] = $data;
                    $i++;
                } else {
                    $result[$index_uid[$duid]]['invites'][] = $invite;
                }
            } catch (\Exception $e) {
                continue;
            }
        }

        return [
            'total' => $total,
            'page' => $pages['page'],
            'limit' => $pages['limit'],
            'list' => $result,
        ];
    }

    /**
     * 待处理邀请
     * @param  int  $uid
     * @param  array  $pages
     * @return array
     * @throws \Exception
     */
    public function unhandle(int $uid, array $pages)
    {
        $icm = new InvitationCardModel();
        $inviteme_cnt = $icm->where(array(['invite_uid', $uid], ['state', 0], ['expired_at', '>', time()]))->count();
        $inviteother_cnt = $icm->where(array(
            ['uid', $uid],
            ['state', '!=', 1],
            ['expired_at', '>', time()],
        ))->orWhere(array(['uid', $uid], ['send_read', 0]))->count();

        if ($pages['limit'] * $pages['page'] <= $inviteme_cnt) {
            $datas = $icm->where(array(
                ['invite_uid', $uid],
                ['state', 0],
                ['expired_at', '>', time()],
            ))->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])->orderBy('id', 'desc')->get();
        } else {
            if ($pages['limit'] * ($pages['page'] - 1) < $inviteme_cnt) {
                $datas = $icm->where(array(
                    ['invite_uid', $uid],
                    ['state', 0],
                    ['expired_at', '>', time()],
                ))->skip(($pages['page'] - 1) * $pages['limit'])->take($inviteme_cnt - $pages['limit'] * ($pages['page'] - 1))->orderBy(
                    'id',
                    'desc'
                )->get();
                $datas2 = $icm->where(array(
                    ['uid', $uid],
                    ['state', '!=', 1],
                    ['expired_at', '>', time()],
                ))->orWhere(array(
                    ['uid', $uid],
                    ['send_read', 0],
                ))->skip(0)->take($pages['limit'] * $pages['page'] - $inviteme_cnt)->orderBy('id', 'desc')->get();
                foreach ($datas2 as $value2) {
                    $datas->push($value2);
                }
            } else {
                $datas = $icm->where(array(
                    ['uid', $uid],
                    ['state', '!=', 1],
                    ['expired_at', '>', time()],
                ))->orWhere(array(
                    ['uid', $uid],
                    ['send_read', 0],
                ))->skip(($pages['page'] - 1) * $pages['limit'] - $inviteme_cnt)->take($pages['limit'])->orderBy(
                    'id',
                    'desc'
                )->get();
            }
        }

        $uids = array_unique(array_merge($datas->pluck('invite_uid')->toArray(), $datas->pluck('uid')->toArray()));
        $users = UserModel::whereIn('uid', $uids)->get([
            'uid',
            'headimgurl',
            'nickname',
            'partner_id',
            'age',
            'star',
            'introduce',
            'expect',
            'height',
            'sex',
            'school',
            'address',
            'home',
            'tag_1',
            'tag_2',
            'tag_3',
            'tag_4',
            'wx_auth',
            'identity_auth',
            'supvip_endat',
        ])->toArray();
        $users = array_combine(array_column($users, 'uid'), $users);
        $partners = PartnerModel::whereIn('id', array_column($users, 'partner_id'))->get()->toArray();
        $partners = array_combine(array_column($partners, 'id'), $partners);
        $partners[0] = null;
        $result = array();
        $index_uid = array();
        $index_inviteuid = array();
        $i = $j = 0;
        foreach ($datas as $data) {
            try {
                $data = $invite = $data->toArray();
                $duid = $data['uid'];
                if ($duid == $uid) {
                    $duid = $data['invite_uid'];
                    if (!isset($index_uid[$duid])) {
                        $index_uid[$duid] = $i;
                        $data['invites'][] = $invite;
                        $user = $users[$duid];
                        $user['invite_cnt'] = $icm->where('invite_uid', $duid)->count();
                        $partner = $partners[$user['partner_id']];
                        $partner['user'] = $user;
                        $data['partner'] = $partner;
                        $result[$i] = $data;
                        $i++;
                    } else {
                        $result[$index_uid[$duid]]['invites'][] = $invite;
                    }
                } else {
                    if (!isset($index_inviteuid[$duid])) {
                        $index_inviteuid[$duid] = $i;
                        $data['ids'] = [$data['id']];
                        $user = $users[$duid];
                        $user['invite_cnt'] = $icm->where('invite_uid', $duid)->count();
                        $partner = $partners[$user['partner_id']];
                        $partner['user'] = $user;
                        $data['partner'] = $partner;
                        $result[$i] = $data;
                        $i++;
                    } else {
                        array_push($result[$index_inviteuid[$duid]]['ids'], $data['id']);
                    }
                }
            } catch (\Exception $exception) {
                throw $exception;
            }
        }

        return [
            'total' => $inviteme_cnt + $inviteother_cnt,
            'page' => $pages['page'],
            'limit' => $pages['limit'],
            'list' => $result,
        ];
    }

    /**
     * 接收到的邀请
     * @param  int  $uid
     * @param  array  $pages
     * @param  bool  $onlyreceive
     * @return array
     */
    public function receives(int $uid, array $pages, bool $onlyreceive = false)
    {
        $icm = new InvitationCardModel();

        // 未读邀请
        $count = $icm->where([['read', 0], ['invite_uid', $uid]])->count();

        if ($onlyreceive) {
            $datas = $icm->where(array(['invite_uid', $uid], ['state', 1]))
                ->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])
                ->orderBy('id', 'desc')->get();
            $total = $icm->where(array(['invite_uid', $uid], ['state', 1]))->count();
        } else {
            $total = $icm->where('invite_uid', $uid)->count();
            $datas = $icm->where('invite_uid', $uid)
                ->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])
                ->orderBy('id', 'desc')->get();
        }

        $result = array();
        foreach ($datas as &$data) {
            try {
                $partner = PartnerModel::where('uid', $data->uid)->first();
                if (collect($partner)->isEmpty()) {
                    $partner = null;
                } else {
                    $user = UserModel::findOrFail($partner->uid, [
                        'uid',
                        'headimgurl',
                        'nickname',
                        'age',
                        'star',
                        'introduce',
                        'expect',
                        'height',
                        'sex',
                        'school',
                        'address',
                        'home',
                        'tag_1',
                        'tag_2',
                        'tag_3',
                        'tag_4',
                        'wx_auth',
                        'identity_auth',
                        'be_vip_at',
                        'supvip_endat',
                    ]);
                    $user->invite_cnt = $icm->where('invite_uid', $data->uid)->count();
                    $partner->setAttribute("user", $user);
                }
                $data->partner = $partner;
                if ($data->state == 0) {
                    $data->sort = 2;
                    $result[] = $data;
                    continue;
                }
                if ($data->state != 0 && $data->expired_at < time()) {
                    $data->sort = 3;
                    $result[] = $data;
                    continue;
                }
            } catch (\Exception $e) {
                continue;
            }
            $data->sort = 4;
            $result[] = $data;
        }

        // 清空阅读邀请通知的记录
        try {
            $ns = new NoticeService();
            $ns->readNotice($uid);
        } catch (\Exception $e) {
        }

        return [
            'total' => $total,
            'page' => $pages['page'],
            'limit' => $pages['limit'],
            'tag_count' => $count,
            'list' => $result,
        ];
    }

    /**
     * 发出的邀请
     * @param  int  $uid
     * @param  array  $pages
     * @param  bool  $onlyreceive
     * @return array
     */
    public function sends(int $uid, array $pages, bool $onlyreceive = false)
    {
        $icm = new InvitationCardModel();

        // 未读通知的数量
        $count = $icm->where(array(['uid', $uid], ['send_read', 0], ['question_type', "!=", 0]))->count();

        $total = $icm->where('uid', $uid)->where('question_type', "!=", 0)->count();
        $datas = $icm->where('uid', $uid)->where('question_type', "!=", 0)
            ->when($onlyreceive, function ($query) {
                /** @var Builder $query */
                return $query->where('state', 1);
            })->orderBy('id', 'desc')->skip(($pages['page'] - 1) * $pages['limit'])
            ->take($pages['limit'])->get();
        foreach ($datas as &$data) {
            try {
                $partner = PartnerModel::where('uid', $data->invite_uid)->first();
                if (collect($partner)->isEmpty()) {
                    $partner = null;
                } else {
                    $user = UserModel::findOrFail($partner->uid, [
                        'uid',
                        'headimgurl',
                        'nickname',
                        'age',
                        'star',
                        'introduce',
                        'expect',
                        'height',
                        'sex',
                        'school',
                        'address',
                        'home',
                        'tag_1',
                        'tag_2',
                        'tag_3',
                        'tag_4',
                        'wx_auth',
                        'identity_auth',
                        'be_vip_at',
                        'supvip_endat',
                    ]);
                    $user->invite_cnt = $icm->where('invite_uid', $data->invite_uid)->count();
                    $partner->setAttribute("user", $user);
                }
                $data->partner = $partner;
            } catch (\Exception $e) {
                continue;
            }
        }

        return [
            'total' => $total,
            'page' => $pages['page'],
            'limit' => $pages['limit'],
            'tag_count' => $count,
            'list' => $datas,
        ];
    }

    /**
     * 所有邀请
     * @param  int  $uid
     * @param  array  $pages
     * @return array
     */
    public function list(int $uid, array $pages)
    {
        $icm = new InvitationCardModel();

        // 未读通知的数量
        $count = $icm->where(array(
                ['uid', $uid],
                ['send_read', 0],
                ['question_type', "!=", 0],
            ))->count() + $icm->where([['read', 0], ['invite_uid', $uid], ['question_type', "!=", 0]])->count();

        $total = $icm->where(array(['uid', $uid], ['question_type', "!=", 0]))->orWhere(array(
            ['invite_uid', $uid],
            ['question_type', "!=", 0],
        ))->count();


        $datas = $icm->where(array(['uid', $uid], ['question_type', "!=", 0]))->orWhere(array(
            ['invite_uid', $uid],
            ['question_type', "!=", 0],
        ))
            ->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])
            ->orderBy('id', 'desc')->get();


        foreach ($datas as &$data) {
            try {
                $suid = $uid == $data->uid ? $data->invite_uid : $data->uid;
                $partner = PartnerModel::where('uid', $suid)->first();
                if (collect($partner)->isEmpty()) {
                    $partner = null;
                } else {
                    $user = UserModel::findOrFail($partner->uid, [
                        'uid',
                        'headimgurl',
                        'nickname',
                        'age',
                        'star',
                        'introduce',
                        'expect',
                        'height',
                        'sex',
                        'school',
                        'address',
                        'home',
                        'tag_1',
                        'tag_2',
                        'tag_3',
                        'tag_4',
                        'wx_auth',
                        'identity_auth',
                        'be_vip_at',
                        'supvip_endat',
                    ]);
                    $user->invite_cnt = $icm->where('invite_uid', $suid)->count();
                    $partner->setAttribute("user", $user);
                }
                $data->partner = $partner;
            } catch (\Exception $e) {
                continue;
            }
        }

        return [
            'total' => $total,
            'page' => $pages['page'],
            'limit' => $pages['limit'],
            'tag_count' => $count,
            'list' => $datas,
        ];
    }

    /**
     * 同意/忽略 邀请
     * @param  int  $invite_id
     * @param  int  $uid
     * @param  int  $state
     * @return bool
     * @throws AlertException
     */
    public function fixstate(int $invite_id, int $uid, int $state)
    {
        $invite = InvitationCardModel::findOrFail($invite_id);
        if ($invite->invite_uid != $uid) {
            throw new AlertException("权限不足", 403);
        }
        if ($invite->state == 1) {
            throw new AlertException("参数错误", 422);
        }
        \DB::beginTransaction();
        try {
            $invite->read = time();
            $invite->state = $state;
            \DB::commit();
            if ($state == 1) {
                $invite->send_read = 0;
                $invite->receive_at = time();
                $invite->save();
                $fs = new FriendService();
                $fs->befriend($invite->uid, $invite->invite_uid, 1, $invite->id);
                try {
                    $ns = new NoticeService();
                    $ns->invitationSuccess($invite->uid, $invite->invite_uid);
                } catch (\Exception $exception) {
                    app('sentry')->captureException($exception);
                }
            } else {
                $invite->save();
            }

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

    /**
     * 阅读 邀请
     * @param  int  $invite_id
     * @param  int  $uid
     * @return bool
     * @throws AlertException
     */
    public function fixread(int $invite_id, int $uid)
    {
        $icm = new InvitationCardModel();
        $invite = $icm->findOrFail($invite_id);

        if (!in_array($uid, [$invite->invite_uid, $invite->uid])) {
            throw new AlertException("权限不足", 403);
        }

        if ($invite->read == 0 && $invite->invite_uid == $uid) {
            $invite->read = time();
            $invite->save();

            return true;
        }

        if ($invite->send_read == 0 && $invite->uid == $uid) {
            $invite->send_read = time();
            $invite->save();

            return true;
        }

        return true;
    }


    /**
     * 获取某人当前邀请数量
     * @param  int  $uid
     * @return array
     */
    public function invitecnt(int $uid)
    {
        $total = InvitationCardModel::where('invite_uid', $uid)->count();
        $ings = InvitationCardModel::where([
            ['invite_uid', $uid],
            ['state', 0],
            ['expired_at', '>', time()],
        ])->count();

        return array(
            'total' => $total,
            'ings' => $ings,
        );
    }
}
