<?php

namespace App\Managers;

use App\Models\Friends\FriendContact;
use App\Models\IM\UserLatestMessage;
use App\Models\IM\UserMessage;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;

class IMManager
{
    /**
     * 是否可以IM通信
     * @param  string  $fromAccount
     * @param  string  $toAccount
     * @return bool
     */
    public function canIm(string $fromAccount, string $toAccount): bool
    {
        $userManager = new UserManager();
        $fromUid = $userManager->getUidByIMAccount($fromAccount);
        $toUid = $userManager->getUidByIMAccount($toAccount);

        if (
            FriendContact::where([
                array('uid', $fromUid), array('friend_uid', $toUid), array('is_blacklist', 1)
            ])->orWhere([
                array('uid', $toUid), array('friend_uid', $fromUid), array('is_blacklist', 1)
            ])->first()
        ) {
            return false;
        }
        return true;
    }

    /**
     * 获取用户的最近消息
     * @param int $userId 获取消息的用户
     * @param array $uids 聊天的相关用户组
     * @return \Illuminate\Support\Collection
     */
    public function getUserLatestMessages(int $userId, array $uids)
    {
        $msgs = UserLatestMessage::where('uid', $userId)
            ->where(function (/** @var Builder $query */$query) use ($uids) {
                $query->orWhereIn('from_uid', $uids);
                $query->orWhereIn('to_uid', $uids);
            })->orderBy('msg_time_stamp', 'desc')
            ->orderBy('seq', 'desc')->get();

        return $msgs;
    }

    /**
     * 标记一条消息未已读
     * @param int $userId 用户
     * @param int $fromUid 发送者
     * @param int $toUid 接收者
     * @param int $timeStamp 消息发送的时间戳
     * @param $random
     * @param $seq
     */
    public function markMessageAsRead(int $userId, int $fromUid, int $toUid, int $timeStamp, $random, $seq)
    {
        UserLatestMessage::where('uid', $userId)
            ->where('to_uid', $toUid)
            ->where('from_uid', $fromUid)
            ->where('msg_time_stamp', $timeStamp)
            ->where('msg_random', $random)
            ->where('seq', $seq)
            ->update([
                'read' => true
            ]);
    }

    /**
     * 删除一条消息
     * @param  int  $userId  用户
     * @param  int  $fromUid  发送者
     * @param  int  $toUid  接收者
     * @param  int  $timeStamp  消息发送的时间戳
     * @param $random
     * @param $seq
     * @throws \Exception
     */
    public function deleteMessage(int $userId, int $fromUid, int $toUid, int $timeStamp, $random, $seq)
    {
        UserLatestMessage::where('uid', $userId)
            ->where('to_uid', $toUid)
            ->where('from_uid', $fromUid)
            ->where('msg_time_stamp', $timeStamp)
            ->where('msg_random', $random)
            ->where('seq', $seq)
            ->delete();
    }

    /**
     * 撤回一条消息
     * @param  int  $userId  用户
     * @param  int  $toUid  接收者
     * @param  int  $timeStamp
     * @param $random
     * @param $seq
     * @throws \Exception
     */
    public function revokeMessage(int $userId, int $toUid, int $timeStamp, $random, $seq)
    {
        UserLatestMessage::where('uid', $userId)
            ->where('to_uid', $toUid)
            ->where('from_uid', $userId)
            ->where('msg_time_stamp', $timeStamp)
            ->where('msg_random', $random)
            ->where('seq', $seq)
            ->delete();

        UserLatestMessage::where('uid', $toUid)
            ->where('to_uid', $toUid)
            ->where('from_uid', $userId)
            ->where('msg_time_stamp', $timeStamp)
            ->where('msg_random', $random)
            ->where('seq', $seq)
            ->delete();
    }

    /**
     * 发送消息后的回调
     *
     * 写入被发方和发送方的最近消息
     * 并保持最近消息不冗余
     */
    public function sendMessageCallback()
    {
        // 写入发送者数据

        // 写入被发送者数据
    }

    public function mapAccountToUserId(array $accounts)
    {
        $userManager = new UserManager();
        return array_combine($accounts, array_map(function ($account) use ($userManager) {
            return $userManager->getUidByIMAccount($account);
        }, $accounts));
    }

    public function createUserLatestMessageByAccount(
        $account,
        $fromAccount,
        $toAccount,
        $msgTime,
        $msgRandom,
        $msgSeq,
        $data,
        $read = false
    ) {
        $userIds = $this->mapAccountToUserId([
            $account,
            $fromAccount,
            $toAccount,
        ]);
        $this->createUserLatestMessageByUserId(
            $userIds[$account] ?? 0,
            $userIds[$fromAccount] ?? 0,
            $userIds[$toAccount] ?? 0,
            $msgTime,
            $msgRandom,
            $msgSeq,
            $data,
            $read
        );
    }

    public function createUserLatestMessageByUserId(
        $userId,
        $fromUserId,
        $toUserId,
        $msgTime,
        $msgRandom,
        $msgSeq,
        $data,
        $read = false
    ) {
        UserLatestMessage::create([
            'uid' => $userId,
            'from_uid' => $fromUserId,
            'to_uid' => $toUserId,
            'msg_time_stamp' => $msgTime,
            'msg_random' => $msgRandom,
            'seq' => $msgSeq,
            'read' => $read,
            'content' => json_encode($data),
        ]);
        $count = UserLatestMessage::where([
                array('uid', $userId), array('to_uid', $toUserId), array('read', 1)
            ])->orWhere([
                array('uid', $userId), array('from_uid', $toUserId), array('read', 1)
            ])->count();
        if (($count - 10) > 0) {
            UserLatestMessage::where([
                array('uid', $userId),
                array('to_uid', $toUserId),
                array('read', 1)
            ])->orWhere([
                array('uid', $userId),
                array('from_uid', $toUserId),
                array('read', 1)
            ])->orderByDesc('msg_time_stamp')->take($count - 10)->delete();
        };
    }

    public function createUserMessageByAccount(
        $account,
        $fromAccount,
        $toAccount,
        $msgTime,
        $msgRandom,
        $msgSeq,
        $data
    ) {
        $userIds = $this->mapAccountToUserId([
            $account,
            $fromAccount,
            $toAccount,
        ]);

        $this->createUserMessageByUserId(
            $userIds[$account] ?? 0,
            $userIds[$fromAccount] ?? 0,
            $userIds[$toAccount] ?? 0,
            $msgTime,
            $msgRandom,
            $msgSeq,
            $data
        );
    }

    public function createUserMessageByUserId(
        $userId,
        $fromUserId,
        $toUserId,
        $msgTime,
        $msgRandom,
        $msgSeq,
        $data
    ) {
        UserMessage::create([
            'uid' => $userId,
            'from_uid' => $fromUserId,
            'to_uid' => $toUserId,
            'msg_time_stamp' => $msgTime,
            'msg_random' => $msgRandom,
            'seq' => $msgSeq,
            'content' => json_encode($data),
        ]);
    }
}
