<?php

namespace App\Http\Controllers\Fpdx;

use App\Exceptions\AlertException;
use App\Http\Controllers\Wechat\SendMsg;
use App\Services\Deed\InvitationService;
use App\Services\Notice\ManageService;
use App\Services\User\TaskService;
use Illuminate\Support\Facades\Redis;
use App\Models\User\Openid;
use App\Models\Fpdx\MessageModel;
use App\Models\User\UserModel;
use App\Models\Fpdx\RoomModel;
use App\Models\Fpdx\PairModel;
use App\Models\Fpdx\RoomProfileModel;
use App\Http\Controllers\Core\User as CoreUser;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Wechat\Media;
use App\Http\Controllers\Wechat\Kfaccount;
use App\Jobs\HandleMessage;

class Message extends Controller
{
    /**
     * 解析消息体
     * @param  \SimpleXMLElement  $message  消息包
     * @return string
     * @throws \App\Exceptions\AlertException
     */
    public function receive(\SimpleXMLElement $message)
    {
        if ($message->MsgType == 'text') {
            switch ($message->Content) {
                case 'TDQLTX':
                    $openData = CoreUser::getUidByOpenid($message->FromUserName);
                    Redis::hset("fpdx_group_room_notives", $openData['uid'], time());
                    $this->systemResponse($message->FromUserName, "退订成功");
                    return "success";
                case '查看申请':
                    //
                case '心动邀请':
                    try {
                        $openData = CoreUser::getUidByOpenid($message->FromUserName);
                        $ins = new InvitationService();
                        $dcnt = $ins->invitecnt($openData['uid']);
                        $dmsg = "点此查看收到的好友申请，共收到{$dcnt['total']}条好友申请";
                        $message->Content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter?launch_type=free&url=%2Fpages%2Ffriend%2Ffriend'>" . $dmsg . "</a>";
                        return SendMsg::text($message);
                    } catch (\Exception $e) {
                        $dmsg = "点此查看收到的好友申请";
                        $message->Content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter?launch_type=free&url=%2Fpages%2Ffriend%2Ffriend'>" . $dmsg . "</a>";
                        return SendMsg::text($message);
                    }
                    break;
                case "退订心动提醒":
                case "退订心动邀请":
                    try {
                        $openData = CoreUser::getUidByOpenid($message->FromUserName);
                        $ms = new ManageService();
                        $ms->updateNoticeByKey($openData['uid'], "flipped_notice", 0);
                        $message->Content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter'>已退订心动提醒, 点此进入小程序</a>";
                        return SendMsg::text($message);
                    } catch (\Exception $e) {
                    }
                    break;
                case "红包":
                    $core = new \App\Http\Controllers\Core\User();
                    $openData = $core->getUidByOpenid($message->FromUserName);
                    $ts = new TaskService();
                    try {
                        $flower = $ts->getVipFlowerEveryDay($openData['uid']);
                        $content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter?launch_type=free&url=%2Fpages%2Frest-of-money%2Frest-of-money'>恭喜你获得小fa：{$flower}朵，点此继续赚小fa。</a>";
                    } catch (AlertException $exception) {
                        $content = $exception->getMessage();
                        if ($exception->getCode() == 102) {
                            $content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter?launch_type=free&url=%2Fpages%2Fvip%2Fvip'>{$content}</a>";
                        } else {
                            $content = "<a data-miniprogram-appid='wx4c1722a4055bd229' data-miniprogram-path='pages/starter/starter?launch_type=free&url=%2Fpages%2Frest-of-money%2Frest-of-money'>{$content}</a>";
                        }
                    }
                    $message->Content = $content;
                    return SendMsg::text($message);
                    break;
            }
            $hides = Redis::smembers("fpdx_hide_msg_key");
            if (empty($hides)) {
            } elseif (in_array($message->Content, $hides)) {
                return "success";
            } else {
            }
        }
        $message = $message->asXML();
        $this->dispatch(new HandleMessage($message));
        return "success";
    }

    /**
     * 处理消息任务
     * @param  \SimpleXMLElement message 消息包
     * @return array|void
     */
    public function handleMsgTask(\SimpleXMLElement $message)
    {
        try {
            $openData = CoreUser::getUidByOpenid($message->FromUserName);
            $room_id = Redis::hget("fpdx_uid_rooms", $openData['uid']);
            if ($room_id) {
                Redis::hset("fpdx_uid_rooms", "{$openData['uid']}_time", time());
                switch ($message->MsgType) {
                    case 'text':
                        $add = array(
                            'send_uid' => $openData['uid'],
                            'receive_uid' => $room_id,
                            'msg_content' => (string)$message->Content,
                            'msg_type' => -1,
                            'create_time' => time()
                        );
                        break;
                    case 'image':
                        $add = array(
                            'send_uid' => $openData['uid'],
                            'receive_uid' => $room_id,
                            'msg_content' => "http://www.koudaidaxue.com/base/media/getImage?url=" . (string)$message->PicUrl,
                            'msg_type' => -8,
                            'create_time' => time()
                        );
                        break;
                    case 'voice':
                        $add = array(
                            'send_uid' => $openData['uid'],
                            'receive_uid' => $room_id,
                            'msg_content' => $message->MediaId,
                            'msg_type' => -11,
                            'create_time' => time()
                        );
                        break;
                    default:
                        return self::systemResponse($message->FromUserName, "您刚刚发送内容，暂不支持转发。（当前仅支持文字/图片）");
                }
                Redis::hset("session_msg_room_{$room_id}", 'last_msg', json_encode($add));
                if ($add['msg_content'] == "【收到不支持的消息类型，暂无法显示】") {
                    return self::systemResponse($message->FromUserName, "您刚刚发送内容，暂不支持转发。（当前仅支持文字/图片）");
                }
                $message_id = \DB::table('fpdx_pair_room_messages')->insertGetId($add);
                if ($room_id == 'xxd') {
                    $littleGuide = new LittleGuide();
                    $littleGuide->message($message_id);
                } else {
                    PairModel::receiveMsg($openData['uid'], $room_id, $message_id);
                    $this->pushKfMsg($message_id);
                }
                return;
            }
        } catch (\Exception $e) {
            return;
        }
    }

    /**
     * 发送系统响应
     * @param  string openid 响应用户openid
     * @param  string content 内容
     * @return array
     */
    public static function systemResponse($openid, $content)
    {
        $array = [
            'touser' => $openid,
            'content' => $content,
            'kf_account' => 'notice@admin'
        ];
        return Kfaccount::text($array);
    }

    /**
     * 聊天消息推送
     * @param  message_id 消息id
     * @return array
     * @throws \ApiException
     */
    public function pushKfMsg($message_id)
    {
        $msgModel = new MessageModel();
        $msg = $msgModel->where('msg_type', '<', 0)->find($message_id);
        if (collect($msg)->isEmpty()) {
            return [
                'code' => 10005,
                'msg' => '未找到该消息'
            ];
        }
        if (in_array($msg->msg_type, [-2, -3, -4, -5, -6, -10])) { # 不转发的内容
            $send_openData = CoreUser::getOpenidByUid($msg->send_uid);
            $response = self::pushWelcome($send_openData['openid'], $msg);
        } else {
            $roomEloqument = new RoomModel();
            $roomData = $roomEloqument->getRoom($msg->receive_uid, $msg->send_uid);
            $rpfModel = new RoomProfileModel();
            $profile = $rpfModel->profile($msg->send_uid, $roomData['member'][0]);
            if ($profile->is_receive_msg != 1) {
                $msg->push_at = time();
                $msg->msg_state = 2;
                $msg->save();
                return;
            }
            $self = UserModel::find($roomData['member'][1]);
            if (empty($self->kf_account)) {
                if (1 == $self->sex) {
                    $self->kf_account = '101@duixiang';
                } else {
                    $self->kf_account = '201@duixiang';
                }
            }
            // 匹配对象uid -> 是否在房间
            $send_room_id = Redis::hget('fpdx_uid_rooms', $roomData['member'][0]);
            if (strcasecmp($msg->receive_uid, $send_room_id) != 0) {
                return [
                    'code' => 10002,
                    'msg' => '对方不在房间'
                ];
            }
            // 匹配对象uid -> 绑定send_openid
            $send_openData = CoreUser::getOpenidByUid($roomData['member'][0]);
            switch ($msg->msg_type) {
                case -1: # 普通消息
                    $array = [
                        'touser' => $send_openData['openid'],
                        'content' => $msg->msg_content,
                        'kf_account' => $self->kf_account
                    ];
                    $response = Kfaccount::text($array);
                    break;
                case -8: # 图片消息
                    $response = Media::uploadImg($msg->msg_content);
                    if ($response['code'] == 0) {
                        $response = Kfaccount::image(
                            $send_openData['openid'],
                            ['media_id' => $response['data']['media_id']],
                            $self->kf_account
                        );
                    }
                    break;
                case -11: # 语音消息
                    $voice = [
                        "media_id" => $msg->msg_content
                    ];
                    $response = Kfaccount::voice($send_openData['openid'], $voice, $self->kf_account);
                    break;
                case -12: # 视频消息
                    $content = json_decode($msg->msg_content, true);
                    $video = [
                        'media_id' => $content['media_id'][0],
                        'thumb_media_id' => $content['thumb_media_id'][0]
                    ];
                    $response = Kfaccount::video($send_openData['openid'], $video, $self->kf_account);
                    break;
                default:
                    return [
                        'code' => 403,
                        'msg' => '未定义的消息类型'
                    ];
            }
        }
        if ($response['code'] == 0) {
            $msg->push_at = time();
            $msg->msg_state = 1;
            $msg->save();
            return [
                'code' => 0,
                'msg' => '成功'
            ];
        } else {
            return [
                'code' => 404,
                'msg' => $response['msg']
            ];
        }
    }

    /**
     * 推送历史消息
     * @param $room_id
     * @param $uid
     * @throws \ApiException
     */
    public function pushHistoryMsg($room_id, $uid)
    {
        // 获取发送者信息
        $roomEloqument = new RoomModel();
        $data = $roomEloqument->getRoom($room_id, $uid);
        $uids = $data['member'];
        $userData = UserModel::find($uids[0]);
        $self = UserModel::find($uids[1]);
        if (empty($self->kf_account)) {
            if (1 == $self->sex) {
                $self->kf_account = '101@duixiang';
            } else {
                $self->kf_account = '201@duixiang';
            }
        }
        // 获取未推送的历史消息
        $msgModel = new MessageModel();
        $where = [
            ['receive_uid', '=', $room_id],
            ['send_uid', '=', $uids[0]],
            ['msg_state', '=', 0]
        ];

        $msgs = $msgModel->where($where)->whereIn('msg_type', [-1, -8, -11])->orderBy('create_time', 'asc')->get();
        $content = "";
        $count = 0;
        foreach ($msgs as $msg) {
            if ($msg->msg_type == -8) {
                $msg->msg_content = "<a href='{$msg->msg_content}'>[图片]</a>";
            }
            if ($msg->msg_type == -11) {
                $msg->msg_content = "<a href='http://msy.pocketuniversity.cn/api/fpdx/msg/push/{$msg->id}'>[点此接收语音消息]</a>";
            }
            $content .= "\n" . date("H:i:m", (int)$msg->create_time) . "\n{$msg->msg_content}\n--------------";
            $count++;
        }
        $send_openData = CoreUser::getOpenidByUid($uid);

        // 推送Kf历史消息
        if (!empty($content)) {
            $rpfModel = new RoomProfileModel();
            $profile = $rpfModel->profile($room_id, $uid);
            if ($profile->is_receive_msg == 0) {
                $msg_state = 2;
            } else {
                $content = "以下是为您同步的未读信息：\n\n" . $content . "\n发送者：{$userData->nickname}\n共计{$count}条,快去回复Ta吧！";
                $array = [
                    'touser' => $send_openData['openid'],
                    'content' => $content,
                    'kf_account' => 'notice@admin'
                ];
                $response = Kfaccount::text($array);
                if ($response['code'] == 0) {
                    $msg_state = 1;
                } else {
                    $msg_state = 0;
                }
            }
            $arg = [];
            foreach ($msgs as $msg) {
                array_push($arg, $msg->id);
            }
            $msgModel->whereIn('id', $arg)->update(['push_at' => time(), 'msg_state' => $msg_state]);
        }
    }

    /**
     * 发送欢迎消息
     * @param  openid 发送openid
     * @param  msg 消息信息集合
     * @return array|void
     */
    private static function pushWelcome($openid, $msg)
    {
        if (!in_array($msg->msg_type, [-6, -10])) {
            return [
                'code' => 10003,
                'msg' => '错误的消息'
            ];
        }
        $contents = json_decode($msg->msg_content, true);
        foreach ($contents as $content) {
            switch ($content['type']) {
                case 'text':
                    $array = [
                        'touser' => $openid,
                        'content' => $content['content'],
                        'kf_account' => isset($content['kf_account']) ? $content['kf_account'] : 'notice@admin'
                    ];
                    Kfaccount::text($array);
                    break;
                case 'image':
                    $response = Media::uploadImg($content['content']);
                    if ($response['code'] == 0) {
                        Kfaccount::image($openid, ['media_id' => $response['data']['media_id']]);
                    }
                    break;
            }
        }
        return;
    }
}
