<?php

namespace App\Http\Controllers\Api\v2;

use App\Components\Functions;
use App\Components\PusherService;
use App\Http\Resources\MessageResource;
use App\Jobs\SendNotificationMessage;
use App\Models\Hostel;
use App\Models\Report;
use App\Models\ReportSale;
use App\Models\ReportSaleType;
use App\Models_v2\Attachment;
use App\Models_v2\Conversation;
use App\Models_v2\DatabaseNotification;
use App\Models_v2\FindSession;
use App\Models_v2\Message;
use App\Models_v2\MessageRead;
use App\Models_v2\RequestConfirm;
use App\Models_v2\Transaction;
use App\Notifications\NewMessage;
use App\Notifications\SearchFoundOwner;
use App\Notifications\SearchFoundRenter;
use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use shweshi\OpenGraph\OpenGraph;

class ConversationController extends BaseController
{
    //
    /**
     * @api {post} /create Tạo cuộc hội thoại
     * @apiName create
     * @apiGroup conversation
     * @apiParam {Number} hostel_id
     * @apiParam {Number} find_session_id
     * @apiParam {String} content
     * @apiDescription Api Tạo cuộc hội thoại
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function create(Request $request)
    {
        $hostelIds = $request->input('hostel_id');
        $findSessionId = $request->input('find_session_id');
        $content = $request->input('content');
        $user = $this->user->id;
        $pusher = \PusherService::getClient();


        $findSession = FindSession::query()
            ->find($findSessionId);


        if (!$findSession) {
            return response([
                'status' => 0
            ]);
        }

        if ($findSession->status == FindSession::CANCEL) {
            return response([
                'status' => 0,
                'message' => 'Phiên tìm kiếm đã bị hủy'
            ]);
        }

        $ownerId = $this->user->id;
        if ($this->user->type == User::STAFF) {
            $ownerId = $this->user->id;
        }

        $staffOwners = User::query()->where('staff_owner_id', $ownerId)->pluck('id')->toArray();
        $staffOwners[] = $ownerId;
        $checkInteractBefore = Conversation::query()
            ->where('find_session_id', $findSession->id)
            ->whereHas('users', function ($q) use ($staffOwners) {
                $q->whereIn('users.id', $staffOwners);
            })
            ->first();

        if ($checkInteractBefore) {
            $users = $checkInteractBefore->users;
            foreach ($users as $user) {
                if ($user->type != User::RENTER) {
                    return response([
                        'status' => 0,
                        'message' => $user->name_text . ' đã nhắn tin cho khách ' . optional($findSession->user)->name_text . ' nên bạn không thể nhắn tin được với khách hàng này'
                    ]);
                }
            }
        }


        $owner = $this->user;
        if ($this->user->type == User::STAFF) {
            $owner = $this->user->owner;
        }

        $numberInteracts = optional($owner)->number_interacts;

        if ($numberInteracts <= 0) {

            return response([
                'status' => -999,
                'message' => 'Bạn đã hết số lượt tương tác với khách thuê, Vui lòng mua thêm lượt tương tác để có thể bắt đầu trò chuyện với khách thuê này'
            ]);
        }

        if ($owner) {

            $owner->decrement('number_interacts');

        }


        $users[] = $user;
        $users[] = $findSession->user_id;

        $check = Conversation::query()
            ->where('find_session_id', $findSessionId)
            ->whereHas('users', function ($q) use ($user) {
                $q->where('users.id', $user);
            })
            ->first();
        if ($check) {
            return response([
                'status' => 1,
                'message' => 'Đã tồn tại cuộc hội thoại với lượt tìm kiếm này',
                'data' => [
                    'id' => $check->id
                ]
            ]);
        }

        sort($users);

        $conversation = Conversation::query()
            ->where('find_session_id', $findSessionId)
            ->where('members', json_encode($users))
            ->first();
        if (!$conversation) {
            $conversation = Conversation::create([
                'name' => '',
                'find_session_id' => $findSessionId
            ]);
        }
        $conversation->users()->sync($users);

        sort($users);
        $conversation->members = json_encode($users);
        $conversation->save();

        if (is_array($hostelIds)) {
            $conversation->hostels()->sync($hostelIds);
        }

        $userTrigger = $conversation->users()
            ->where('users.id', '<>', $user)
            ->first();


        $messageOne = Message::create([
            'from' => $user,
            'type' => 'text',
            'content' => !empty($content) ? $content : 'Chào bạn, mình đang có phòng trống cần cho thuê có thể phù hợp với nhu cầu của bạn',
            'conversation_id' => $conversation->id
        ]);


        $userConversations = $conversation->users;
        foreach ($userConversations as $userConversation) {
            MessageRead::create([
                'message_id' => $messageOne->id,
                'user_id' => $userConversation->id,
                'conversation_id' => $conversation->id,
                'read_at' => ($userConversation->id == $this->user->id) ? Carbon::now()->toDateTimeString() : null
            ]);
        }


        if (is_array($hostelIds)) {
            $messageTwo = Message::create([
                'from' => $user,
                'type' => 'hostels',
                'conversation_id' => $conversation->id,
                'content' => null
            ]);
            $messageTwo->hostels()->sync($hostelIds);

            foreach ($userConversations as $userConversation) {
                MessageRead::create([
                    'message_id' => $messageTwo->id,
                    'user_id' => $userConversation->id,
                    'conversation_id' => $conversation->id,
                    'read_at' => ($userConversation->id == $this->user->id) ? Carbon::now()->toDateTimeString() : null
                ]);
            }

            $retValTwo = Functions::getMessageArr($messageTwo);

            $pusher->trigger('chat-v2-' . $this->user->id, 'v2-new-message', $retValTwo);
            if ($userTrigger) {
                $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retValTwo);
                if (Functions::checkUserOnlineNoConversationV2($userTrigger->id)) {
                    \Notification::send($userTrigger, new NewMessage(
                        $this->user,
                        $messageTwo
                    ));
                }
            }
        }


        $conversation->date_message = Carbon::now()->toDateTimeString();
        $conversation->save();

        $retValOne = Functions::getMessageArr($messageOne);
        $pusher->trigger('chat-v2-' . $this->user->id, 'v2-new-message', $retValOne);

        if ($userTrigger) {

            $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retValOne);

            if (Functions::checkUserOnlineNoConversationV2($userTrigger->id)) {
                \Notification::send($userTrigger, new NewMessage(
                    $this->user,
                    $messageOne
                ));
            }
        }
        $retVal = $this->formatConversationResponse($conversation);

        return response([
            'status' => 1,
            'message' => 'Thành công',
            'data' => $retVal
        ]);

    }

    /**
     * @api {post} /create-by-users Tạo cuộc hội thoại theo users
     * @apiName create-by-users
     * @apiGroup conversation
     * @apiParam {Array} user_ids
     * @apiDescription Api Tạo cuộc hội thoại theo users
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createByUsers(Request $request)
    {
        $userIds = $request->input('user_ids');
        $isSub = $request->input('is_sub_number_interact');

        $owner = $this->user;
        if ($this->user->type == User::STAFF) {
            $owner = $this->user->owner;
        }
        if (!empty($isSub)) {
            if ($owner->number_interacts <= 0) {
                return response([
                    'status' => 0,
                    'message' => 'Bạn không còn đủ số lượt tương tác'
                ]);
            }
            $owner->decrement('number_interacts');
        }
        if (!is_array($userIds) && empty($userIds)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }
        sort($userIds);
        $conversation = Conversation::query()
            ->where('members', json_encode($userIds))
            ->first();
        if (!$conversation) {
            $conversation = Conversation::create([
                'name' => '',
            ]);
        }
        $conversation->users()->sync($userIds);
        sort($userIds);
        $conversation->members = json_encode($userIds);
        $conversation->save();


        $conversation = Conversation::find($conversation->id);
        $retVal = $this->formatConversationResponse($conversation);


        return response([
            'status' => 1,
            'message' => 'Thành công',
            'data' => $retVal
        ]);

    }

    /**
     * @api {get} /detail Chi tiết cuộc hội thoại
     * @apiName detail
     * @apiGroup conversation
     * @apiDescription Api Chi tiết cuộc hội thoại
     * @apiParam {String} id
     * @apiParam {String} room_id
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function detail(Request $request)
    {
        $id = $request->input('id');
        $roomId = $request->input('room_id');
        $conversation = Conversation::query()
            ->when(!empty($id), function ($q) use ($id) {
                $q->where('id', $id);
            })
            ->when(!empty($roomId), function ($q) use ($roomId) {
                $q->where('room_id', $roomId)
                    ->where('is_find', false);
            })
            ->first();
        if (!$conversation) {
            return response([
                'status' => 0,
                'message' => 'Không tìm thấy cuộc hội thoại'
            ]);
        }

        $retVal = $this->formatConversationResponse($conversation);


        return response([
            'status' => 1,
            'message' => 'Thành công',
            'data' => $retVal
        ]);

    }

    /**
     * @api {post} /get-by-users Lay cuoc hoi thoai
     * @apiName get-by-users
     * @apiGroup conversation
     * @apiParam {Array} user_ids
     * @apiDescription Api Lay cuoc hoi thoai
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function getConversationByUsers(Request $request)
    {
        $userIds = $request->input('user_ids');
        if (!is_array($userIds) && empty($userIds)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $item = Conversation::query()
            ->where(function ($q) use ($userIds) {
                foreach ($userIds as $userId) {
                    $q->where('members', 'LIKE', '%' . $userId . '%');
                }
            })
            ->whereNull('room_id')
            ->whereNull('hostel_id')
            ->has('users', count($userIds))
            ->first();

        if (!$item) {
            return response([
                'status' => 1,
                'data' => null
            ]);
        }

        $retVal = $this->formatConversationResponse($item);
        return response([
            'status' => 1,
            'data' => $retVal
        ]);
    }

    /**
     * @api {post} /create-by-renter Tạo cuộc hội thoại bới người trọ
     * @apiName create-by-renter
     * @apiGroup conversation
     * @apiParam {String} content
     * @apiParam {String} hostel_id
     * @apiParam {Array} users Mảng user tham gia (bao gồm cả người tạo - 2 phần tử)
     * @apiDescription Api Tạo cuộc hội thoại bới người trọ
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createByRenter(Request $request)
    {
        $content = $request->input('content');
        $hostelId = $request->input('hostel_id');
        $users = $request->input('users');
        if (empty($users)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }
        $user = $this->user->id;
        $pusher = \PusherService::getClient();
        sort($users);
        $conversation = Conversation::query()
            ->where('members', json_encode($users))
            ->first();
        if (!$conversation) {
            $conversation = Conversation::create([
                'name' => '',
            ]);
        } else {
            if ($conversation->status == Conversation::ARCHIVED) {
                $conversation->status = null;
                $conversation->save();
            }
        }

        $conversation->users()->sync($users);
        sort($users);
        $conversation->members = json_encode($users);
        $conversation->save();

        $userTrigger = $conversation->users()
            ->where('users.id', '<>', $user)
            ->first();

        $messageOne = null;
        if (!empty($content)) {
            $messageOne = Message::create([
                'from' => $user,
                'type' => 'text',
                'content' => $content,
                'conversation_id' => $conversation->id
            ]);
        }


        $userConversations = $conversation->users;

        if (!empty($messageOne)) {
            foreach ($userConversations as $userConversation) {
                MessageRead::create([
                    'message_id' => $messageOne->id,
                    'user_id' => $userConversation->id,
                    'conversation_id' => $conversation->id,
                    'read_at' => ($userConversation->id == $this->user->id) ? Carbon::now()->toDateTimeString() : null
                ]);
            }


            $conversation->date_message = Carbon::now()->toDateTimeString();
            $conversation->save();

            $retValOne = Functions::getMessageArr($messageOne);
            $pusher->trigger('chat-v2-' . $this->user->id, 'v2-new-message', $retValOne);

            if ($userTrigger) {

                $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retValOne);

                if (Functions::checkUserOnlineNoConversationV2($userTrigger->id)) {
                    \Notification::send($userTrigger, new NewMessage(
                        $this->user,
                        $messageOne
                    ));
                }
            }
        }


        if (!empty($hostelId)) {
            $hostelIds = [$hostelId];
            $messageTwo = Message::create([
                'from' => $user,
                'type' => 'hostels',
                'conversation_id' => $conversation->id,
                'content' => null
            ]);
            $messageTwo->hostels()->sync($hostelIds);

            foreach ($userConversations as $userConversation) {
                MessageRead::create([
                    'message_id' => $messageTwo->id,
                    'user_id' => $userConversation->id,
                    'conversation_id' => $conversation->id,
                    'read_at' => ($userConversation->id == $this->user->id) ? Carbon::now()->toDateTimeString() : null
                ]);
            }

            $retValTwo = Functions::getMessageArr($messageTwo);

            $pusher->trigger('chat-v2-' . $this->user->id, 'v2-new-message', $retValTwo);
            if ($userTrigger) {
                $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retValTwo);
                if (Functions::checkUserOnlineNoConversationV2($userTrigger->id)) {
                    \Notification::send($userTrigger, new NewMessage(
                        $this->user,
                        $messageTwo
                    ));
                }
            }
        }

        $retVal = $this->formatConversationResponse($conversation);


        return response([
            'status' => 1,
            'message' => 'Thành công',
            'data' => $retVal
        ]);

    }

    /**
     * @api {get} /list Danh sách hội thoại
     * @apiName list
     * @apiGroup conversation
     * @apiParam {Number} find_session_id
     *  * @apiParam {Number} limit
     *  * @apiParam {Number} offset
     * @apiParam {Number} is_archived 1 hoặc 0. 1 là lấy các cuộc hội thoại đã bị archive. 0 là ko. Mặc định là 0
     * @apiDescription Api Danh sách hội thoại
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function index(Request $request)
    {
        $userId = $this->user->id;
        $limit = $request->input('limit', 10);
        $offset = $request->input('offset', 0);
        $findSessionId = $request->input('find_session_id');
        $archived = $request->input('is_archived');
        $name = $request->input('name');
        $class = $this;
        //dd($this->user->type);
        //dd($this->user->id);
        $conversations = Conversation::query()
            ->whereHas('users', function ($q) use ($userId) {
                $q->where('users.id', $userId);
            })
            ->when(!empty($findSessionId), function ($q) use ($findSessionId) {
                $q->where('find_session_id', $findSessionId);
            })
            ->when(!empty($name), function ($q) use ($name, $userId) {
                $q->where(function ($q) use ($name, $userId) {
                    $q->orwhereHas('users', function ($q) use ($name, $userId) {
                        $q->where('users.id', '<>', $userId)->where('users.name', 'LIKE', '%' . $name . '%');
                    });
                    $q->orwhereHas('hostel', function ($q) use ($name, $userId) {
                        $q->where('hostels.name', 'LIKE', '%' . $name . '%');
                    });
                    $q->orwhereHas('room', function ($q) use ($name, $userId) {
                        $q->where('rooms.name', 'LIKE', '%' . $name . '%');
                    });
                });
            });


        if ($this->user->type == User::RENTER) {
            $owner = $this->user->owner_info;
           // dd($owner->id);
            if (!empty($owner)) {
                if (!$owner->allow_renter_view_hostel_group) {
                    $conversations = $conversations->where(function ($q) {
                        $q->orwhere(function ($q2) {
                            $q2->orWhereNull('conversation_find_hostels.room_id');
                            $q2->orWhereNotNull('conversation_find_hostels.room_id');
                        });
                        $q->where(function ($q2) {
                            $q2->whereNull('conversation_find_hostels.hostel_id');

                        });
                        $q->orwhere(function ($q2) {
                            $q2->WhereNotNull('conversation_find_hostels.room_id');
                            $q2->WhereNotNull('conversation_find_hostels.hostel_id');
                        });

                    });
                }
                if (!$owner->allow_renter_view_room_group) {

                    $conversations = $conversations->where(function ($q) {
                        $q->orwhere(function ($q2) {
                            $q2->orWhereNull('conversation_find_hostels.hostel_id');
                            $q2->orWhereNotNull('conversation_find_hostels.hostel_id');
                        });
                        $q->where(function ($q2) {
                            $q2->whereNull('conversation_find_hostels.room_id');
                        });

                        $q->orwhere(function ($q2) {
                            $q2->WhereNull('conversation_find_hostels.room_id');
                            $q2->WhereNull('conversation_find_hostels.hostel_id');
                        });
                    });
                }
            }
        }
        $conversations = $conversations->when(!empty($archived), function ($q) {
            $q->where('status', Conversation::ARCHIVED);
        }, function ($q) {
            $q->where(function ($q) {
                $q->orwhere('status', '<>', Conversation::ARCHIVED);
                $q->orwhereNull('status');
            });
        })
            ->with('messages')
            ->with('hostels')
            ->with('hostel')
            ->with('room')
            ->where(function ($q) {
                $q->orWhere(function ($q) {
                    $q->where('is_find', false);
                    $q->where('is_manual', false);
                    $q->where(function ($q) {
                        $q->orHas('hostel');
                        $q->orHas('room');
                    });
                });
                $q->orWhere('is_manual', true);
                $q->orWhere(function ($q) {
                    $q->where('is_find', true)->has('messages');
                });
                // $q->orHas('messages');

            })
            ->limit($limit)
            ->offset($offset)
            ->orderBy('date_message', 'desc')
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($item) use ($class) {
                return $class->formatConversationResponse($item);
            });

        return response([
            'status' => 1,
            'data' => $conversations
        ]);
    }

    /**
     * @api {post} /update-allow-tenant-reply Cập nhật cho phép khách thuê rep
     * @apiName update-allow-tenant-reply
     * @apiGroup conversation
     * @apiParam {Number} conversation_id
     *  * @apiParam {String} allow_tenant_reply
     * @apiDescription Api Cập nhật cho phép khách thuê rep
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function updateAllowTenantReply(Request  $request)
    {
        $conversationId = $request->input('conversation_id');
        $allowRep = $request->input('allow_tenant_reply');
        $conversation = Conversation::find($conversationId);
        if(!$conversation)
        {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        if(!empty($allowRep))
        {
            $conversation->allow_tenant_reply = true;
        } else {
            $conversation->allow_tenant_reply = false;
        }

        $conversation->save();
        return response([
            'status' => 1,
            'message' => 'Thành công'
        ]);

    }

    public function formatConversationResponse($item)
    {
        $userJoinDate = null;
        $userJoin = \DB::table('user_conversation_find_hostels')
            ->where('conversation_id', $item->id)
            ->where('user_id', '=', $this->user->id)
            ->first();
        if ($userJoin) {
            if (!empty($userJoin)) {
                $userJoinDate = $userJoin->created_at;
            }
        }

        $lastMessage = $item->messages()
            ->where('type', '<>', 'system')
            ->when(!empty($userJoinDate), function ($q) use ($userJoinDate) {
                $q->where('created_at', '>=', $userJoinDate);
            })
            ->orderBy('id', 'desc')
            ->first();
        $otherUser = $item->getOtherUserAttribute($this->user);

        $unReadMessage = MessageRead::query()
            ->where('user_id', $this->user->id)
            ->where('conversation_id', $item->id)
            ->whereNull('read_at')
            ->count();
        $name = $item->name;
        $image = $item->image;
        if (!$item->is_find) {
            if (!$item->is_manual) {
                if (!empty($item->hostel_id)) {
                    $name = optional($item->hostel)->name;
                    $image = optional($item->hostel)->image;
                } else if (!empty($item->room_id)) {
                    $name = optional($item->room)->name . ' (' . optional(optional($item->room)->hostel)->name . ')';
                    $image = optional($item->room)->image;
                }
            }
        } else {
            if ($item->users->count() <= 2) {
                $name = optional($otherUser)->name_text;
                $image = optional($otherUser)->image;
            } else {
                $nameArr = $item->users->pluck('name')->toArray();
                $name = implode(', ', $nameArr);
            }
        }

        $type = 0;

        if ($item->users->count() == 2 && empty($item->hostel_id) && empty($item->room_id)) {
            $type = 1; // 1-1
        } else if (!empty($item->hostel_id)) {
            $type = 2; // Loai group nha tro
        } else if (!empty($item->room_id)) {
            $type = 3; // Loai group phong tro
        } else if ($item->is_manual) {
            $type = 4; // group tu tao
        }

        return [
            "id" => $item->id,
            "name" => $name,
            "image" => $image,
            "last_message" => !empty($lastMessage) ? [
                "id" => $lastMessage->id,
                "type" => $lastMessage->type,
                "display_text" => $lastMessage->display_text,
                "created_at" => optional($lastMessage->created_at)->format('d/m/Y H:i')
            ] : null,
            "hostels" => $item->hostels->map(function ($item) {
                return [
                    'id' => $item->id,
                    'name' => $item->name
                ];
            }),
            "find_session_id" => $item->find_session_id,
            "unread_count" => $unReadMessage,
            'created_at' => $item->created_at->format('d/m/Y H:i'),
            'status' => $item->status,
            'type' => $type,
            'allow_tenant_reply' => $item->allow_tenant_reply,
            'users' => $item->users->map(function ($item) {
                return [
                    'id' => $item->id,
                    'name' => $item->name,
                    'image' => $item->image,
                    'phone' => $item->phone,
                    'type' => $item->type
                ];
            })
        ];
    }

    /**
     * @api {get} /messages Danh sách tin nhắn
     * @apiName messages
     * @apiGroup conversation
     * @apiParam {Number} limit
     * @apiParam {Number} offset
     * @apiParam {Number} conversation_id
     * @apiDescription Api Danh sách tin nhắn
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function getMessages(Request $request)
    {
        $conversationId = $request->input('conversation_id');
        $limit = $request->input('limit', 10);
        $lastId = $request->input('last_id');
        $conversation = Conversation::find($conversationId);
        if (!$conversation) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        MessageRead::query()
            ->where('user_id', $this->user->id)
            ->where('conversation_id', $conversationId)
            ->whereNull('read_at')
            ->update(['read_at' => Carbon::now()->toDateTimeString()]);
        $userJoinDate = null;
        $userJoin = \DB::table('user_conversation_find_hostels')
            ->where('conversation_id', $conversation->id)
            ->where('user_id', '=', $this->user->id)
            ->first();
        if ($userJoin) {
            if (!empty($userJoin)) {
                $userJoinDate = $userJoin->created_at;
            }
        }
        $users = $conversation->users->pluck('id')->toArray();
        $messages = Message::query()
            ->when(!empty($userJoinDate), function ($q) use ($userJoinDate) {
                $q->where('created_at', '>=', $userJoinDate);
            })
            ->where('conversation_id', $conversationId)
            ->whereHas('sender', function ($q) use ($users) {
                $q->whereIn('users.id', $users);
            })
            ->with('sender')
            ->with('attachments')
            ->with('requestConfirm')
            ->limit($limit)
            ->when(!empty($lastId), function ($q) use ($lastId) {
                $q->where('message_find_hostels.id', '<', $lastId);
            })
            ->orderBy('id', 'desc')
            ->get()
            ->map(function ($item) {
                $sender = optional($item->sender);
                $attachments = $item->attachments;
                $hostels = $item->hostels;
                $requestConfirm = optional($item->requestConfirm);

                return [
                    "id" => $item->id,
                    "type" => $item->type,
                    "created_at" => $item->created_at->format('d/m/Y H:i'),
                    "sender" => [
                        "id" => $sender->id,
                        "name" => $sender->name_text,
                        "phone" => $sender->phone,
                        "avatar" => $sender->image
                    ],
                    "content" => $item->content,
                    "attachments" => $attachments->map(function ($item) {
                        return [
                            "id" => $item->id,
                            "type" => $item->type,
                            "thumbnail" => $item->thumbnail(),
                            "url" => $item->url(),
                            "duration" => $item->duration(),
                            "width" => $item->width(),
                            "height" => $item->height()
                        ];
                    }),
                    "hostels" => $hostels->map(function ($item) {
                        return [
                            "id" => $item->id,
                            "name" => $item->name,
                            "image" => $item->image,
                            "address" => $item->address,
                            'province_name' => optional($item->province)->name,
                            'district_name' => optional($item->district)->name,
                            'ward_name' => optional($item->ward)->name,
                            "desc" => $item->desc
                        ];
                    }),
                    "location" => [
                        "longitude" => $item->lng,
                        "latitude" => $item->lat
                    ],
                    'preview' => [
                        'url' => !empty($item->preview) ? isset($item->preview['url']) ? $item->preview['url'] : null : null,
                        'title' => !empty($item->preview) ? isset($item->preview['title']) ? $item->preview['title'] : null : null,
                        'desc' => !empty($item->preview) ? isset($item->preview['description']) ? $item->preview['description'] : null : null,
                        'image' => !empty($item->preview) ? isset($item->preview['image']) ? $item->preview['image'] : null : null
                    ],
                    'transaction' => [
                        'id' => $requestConfirm->id,
                        'request_by' => $requestConfirm->request_by,
                        'request_by_name' => optional($requestConfirm->userRequestBy)->name_text,
                        'status' => $requestConfirm->status,
                        'accepts' => $requestConfirm->accepts
                    ]

                ];
            });

        return response([
            'status' => 1,
            'data' => $messages
        ]);
    }

    /**
     * @api {post} /send-message Gửi tin nhắn
     * @apiName send-message
     * @apiGroup conversation
     * @apiDescription Api gửi tin nhắn
     * @apiParam {String} conversation_id
     * @apiParam {String} content
     * @apiParam {String} ui_id
     * @apiParam {String} lat
     * @apiParam {String} lng
     * @apiParam {String} type
     * @apiParam {File} attachments[]
     *
     * @apiParam {File} thumbnails[]
     * @apiParam {Array} meta_attachments[]
     * @apiParam {Array} hostels[]
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function sendMessage(Request $request)
    {
        $content = $request->input('content');
        $conversationId = $request->input('conversation_id');
        $type = $request->input('type');
        $attachments = $request->file('attachments');
        $thumbnails = $request->file('thumbnails');
        //	dd($thumbnails);
        $metaAttachments = $request->input('meta_attachments');
        $uiid = $request->input('ui_id');
        $hostels = $request->input('hostels');
        $userId = $this->user->id;

        $metaAttachments = json_decode($metaAttachments, true);
        $conversation = Conversation::find($conversationId);

        if (!$conversation) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }
        $ownerId = $this->user->id;

        if ($this->user->type == User::STAFF) {
            $ownerId = $this->user->staff_owner_id;
        }

        $staffOwners = User::query()->where('staff_owner_id', $ownerId)->pluck('id')->toArray();
        $staffOwners[] = $ownerId;


//        if (in_array($conversation->status, [Conversation::INACTIVE, Conversation::ARCHIVED])) {
//            return response([
//                'status' => 0,
//                'message' => 'Không thể trả lời cuộc hội thoại này'
//            ]);
//        }

        $userArr = $conversation->users->pluck('id')->toArray();
        if (!in_array($userId, $userArr)) {
            return response([
                'status' => 0,
                'message' => 'Không thể trả lời cuộc hội thoại này'
            ]);
        }

        $message = Message::create([
            'ui_id' => $uiid,
            'conversation_id' => $conversationId,
            'content' => $content,
            'from' => $userId,
            'lat' => $request->input('lat'),
            'lng' => $request->input('lng'),
            'type' => $type
        ]);

        if (is_array($metaAttachments)) {
            foreach ($attachments as $key => $attachment) {
                $metaAttachment = $metaAttachments[$key];
                $thumbnail = $thumbnails[$key];
                $attachmentArr['message_id'] = $message->id;

                if ($metaAttachment['type'] == 'image') {
                    $attachmentArr['type'] = 'image';
                    $attachmentFile = Functions::uploadImage($attachment);
                    $attachmentArr['image'] = $attachmentFile;
                    if ($thumbnail != -1) {
                        $attachmentArr['thumbnail'] = Functions::uploadImage($thumbnail);
                    }
                    $attachmentArr['image_height'] = $metaAttachment['height'];
                    $attachmentArr['image_width'] = $metaAttachment['width'];
                } else if ($metaAttachment['type'] == 'audio') {
                    $attachmentArr['type'] = 'audio';
                    $attachmentFile = Functions::uploadFile($attachment);
                    $attachmentArr['audio'] = $attachmentFile;
                    $attachmentArr['audio_duration'] = $metaAttachment['duration'];

                } else if ($metaAttachment['type'] == 'video') {
                    $attachmentFile = Functions::uploadFile($attachment);
                    $attachmentArr['type'] = 'video';
                    $attachmentArr['video'] = $attachmentFile;
                    $attachmentArr['video_duration'] = $metaAttachment['duration'];
                    if ($thumbnail != -1) {
                        $attachmentArr['video_thumbnail'] = Functions::uploadImage($thumbnail);
                    }
                }
                Attachment::create($attachmentArr);
            }
        }

        if (is_array($hostels)) {
            $message->hostels()->sync($hostels);
        }

        $conversation->date_message = Carbon::now()->toDateTimeString();
        $conversation->save();

        $users = $conversation->users;
        foreach ($users as $user) {
            MessageRead::create([
                'message_id' => $message->id,
                'user_id' => $user->id,
                'conversation_id' => $conversationId,
                'read_at' => ($user->id == $this->user->id || Functions::checkUserOnlineConversationV2($user->id, $conversationId)) ? Carbon::now()->toDateTimeString() : null
            ]);
        }

        $sender = optional($message->sender);
        $attachments = $message->attachments;
        $hostels = $message->hostels;

        preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $content, $match);
        $urls = $match[0];
        if (!empty($urls)) {
            $url = $urls[0];
            $openGraph = \OpenGraph::fetch($url);
            if (!empty($openGraph)) {
                if (isset($openGraph['title'])) {
                    $message->type = 'previewURL';
                }
                $message->preview = $openGraph;
                $message->save();
            }
        }

        $retVal = [
            "id" => $message->id,
            'ui_id' => $uiid,
            'conversation_id' => $conversationId,
            'display_text' => $message->display_text,
            "type" => $message->type,
            "created_at" => $message->created_at->format('d/m/Y H:i'),
            "sender" => [
                "id" => $sender->id,
                "name" => $sender->name_text,
                "phone" => $sender->phone,
                "avatar" => $sender->image
            ],
            "content" => $message->content,
            "attachments" => $attachments->map(function ($item) {
                return [
                    "id" => $item->id,
                    "type" => $item->type,
                    "thumbnail" => $item->thumbnail(),
                    "url" => $item->url(),
                    "duration" => $item->duration(),
                    "width" => $item->width(),
                    "height" => $item->height()
                ];
            }),
            "hostels" => $hostels->map(function ($item) {
                return [
                    "id" => $item->id,
                    "name" => $item->name,
                    "image" => $item->image,
                    "address" => $item->address,
                    "desc" => $item->desc
                ];
            }),
            "location" => [
                "longitude" => $message->lng,
                "latitude" => $message->lat
            ],
            'preview' => [
                'url' => !empty($message->preview) ? isset($message->preview['url']) ? $message->preview['url'] : null : null,
                'title' => !empty($message->preview) ? isset($message->preview['title']) ? $message->preview['title'] : null : null,
                'desc' => !empty($message->preview) ? isset($message->preview['description']) ? $message->preview['description'] : null : null,
                'image' => !empty($message->preview) ? isset($message->preview['image']) ? $message->preview['image'] : null : null
            ]

        ];

        $pusher = \PusherService::getClient();

        $userTriggers = $conversation->users()
            ->where('users.id', '<>', $userId)
            ->get();

        foreach ($userTriggers as $userTrigger) {

            if ($userTrigger) {
                $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retVal);
//                if (Functions::checkUserOnlineV2($userTrigger->id, $conversationId)) {
                    \Notification::send($userTrigger, new NewMessage(
                        $this->user,
                        $message
                    ));
//                }
            }
        }
        $pusher->trigger('chat-v2-' . $userId, 'v2-new-message', $retVal);

        return response([
            'status' => 1,
            'data' => $retVal
        ]);
    }

    /**
     * @api {post} /send-confirm Gửi xác nhận
     * @apiName send-confirm
     * @apiGroup conversation
     * @apiDescription Api Gửi xác nhận
     * @apiParam {String} conversation_id
     * @apiParam {Array} accepts
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function sendConfirm(Request $request)
    {
        $conversationId = $request->input('conversation_id');
        $accepts = $request->input('accepts');
        $type = 'transaction';
        $userId = $this->user->id;

        $conversation = Conversation::find($conversationId);

        if (!$conversation) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

//		if ( ! empty( $conversation->request_confirm_id ) ) {
//			return response( [
//				'status'  => 0,
//				'message' => 'Đã có yêu cầu xác nhận trước đó'
//			] );
//		}

        $requestConfirm = RequestConfirm::create([
            'conversation_id' => $conversationId,
            'request_by' => $userId,
            'accepts' => $accepts,
            'status' => RequestConfirm::WAIT
        ]);

        $conversation->request_confirm_id = $requestConfirm->id;
        $conversation->save();

        $message = Message::create([
            'conversation_id' => $conversationId,
            'from' => $userId,
            'type' => $type,
            'request_confirm_id' => $requestConfirm->id,
            'content' => null
        ]);

        $conversation->date_message = Carbon::now()->toDateTimeString();
        $conversation->save();

        $users = $conversation->users;
        foreach ($users as $user) {
            MessageRead::create([
                'message_id' => $message->id,
                'user_id' => $user->id,
                'conversation_id' => $conversationId,
                'read_at' => $user->id == $this->user->id ? Carbon::now()->toDateTimeString() : null
            ]);
        }

        $sender = optional($message->sender);

        $retVal = [

            "id" => $message->id,
            'display_text' => $message->display_text,
            'conversation_id' => $conversationId,
            "type" => $message->type,
            "created_at" => $message->created_at->format('d/m/Y H:i'),
            "sender" => [
                "id" => $sender->id,
                "name" => $sender->name_text,
                "phone" => $sender->phone,
                "avatar" => $sender->image
            ],
            "content" => $message->content,
            "attachments" => [],
            "hostels" => [],
            "location" => [
                "longitude" => $message->lng,
                "latitude" => $message->lat
            ],
            'preview' => [
                'url' => !empty($message->preview) ? isset($message->preview['url']) ? $message->preview['url'] : null : null,
                'title' => !empty($message->preview) ? isset($message->preview['title']) ? $message->preview['title'] : null : null,
                'desc' => !empty($message->preview) ? isset($message->preview['description']) ? $message->preview['description'] : null : null,
                'image' => !empty($message->preview) ? isset($message->preview['image']) ? $message->preview['image'] : null : null
            ],
            'transaction' => [
                'id' => $requestConfirm->id,
                'request_by' => $requestConfirm->request_by,
                'request_by_name' => optional($requestConfirm->userRequestBy)->name_text,
                'status' => $requestConfirm->status,
                'accepts' => $requestConfirm->accepts
            ]

        ];

        $pusher = \PusherService::getClient();

        $userTrigger = $conversation->users()
            ->where('users.id', '<>', $userId)
            ->first();

        if ($userTrigger) {

            $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retVal);
            $pusher->trigger('chat-v2-' . $userId, 'v2-new-message', $retVal);

            if (Functions::checkUserOnlineV2($userTrigger->id, $conversationId)) {
                \Notification::send($userTrigger, new NewMessage(
                    $this->user,
                    $message
                ));
            }
        }

        return response([
            'status' => 1,
            'data' => $retVal
        ]);
    }

    /**
     * @api {post} /confirm Xác nhận
     * @apiName confirm
     * @apiGroup conversation
     * @apiDescription Api Xác nhận
     * @apiParam {String} conversation_id
     * @apiParam {String} request_confirm_id
     * @apiParam {String} find_session_id
     * @apiParam {Array} accepts
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function confirm(Request $request)
    {
        $requestConfirmId = $request->input('request_confirm_id');
        $accepts = $request->input('accepts');
        $findSessionId = $request->input('find_session_id');
        $conversationId = $request->input('conversation_id');

        $requestConfirm = RequestConfirm::find($requestConfirmId);
        if (!$requestConfirm) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $conversation = Conversation::find($conversationId);

        if (!$conversation) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        if (!is_array($accepts)) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }
        $users = $conversation->users;
        $ownerId = null;
        $renterId = null;
        foreach ($users as $user) {
            if ($user->type == User::OWNER) {
                $ownerId = $user->id;
            } else {
                $renterId = $user->id;
            }
        }

        try {
            \DB::beginTransaction();
            if (count($accepts) >= 2) {
                $requestConfirm->status = RequestConfirm::CONFIRMED;
            }
            $requestConfirm->accepts = $accepts;
            $requestConfirm->save();
            if (count($accepts) >= 2) {
                $findSession = FindSession::find($findSessionId);
                if ($findSession) {
                    $findSession->status = FindSession::FOUND;
                    $findSession->save();

                    $conversation->status = Conversation::ARCHIVED;
                    $conversation->save();

                }

                Conversation::query()
                    ->where('find_session_id', $findSessionId)
                    ->update([
                        'status' => Conversation::ARCHIVED
                    ]);

                if (!empty($ownerId)) {
                    User::query()
                        ->where('id', $ownerId)
                        ->decrement('balance', Functions::getChargeOwner($ownerId));

                    Transaction::create([
                        'user_id' => $ownerId,
                        'amount' => 0 - Functions::getChargeOwner($ownerId),
                        'request_confirm_id' => $requestConfirmId,
                        'type' => Transaction::FIND_RENTER_SUCCESS
                    ]);
                }

                if (!empty($renterId)) {
                    User::query()
                        ->where('id', $renterId)
                        ->increment('balance', option('add_renter', 100));

                    Transaction::create([
                        'user_id' => $renterId,
                        'amount' => option('add_renter', 100),
                        'request_confirm_id' => $requestConfirmId,
                        'type' => Transaction::FIND_HOSTEL_SUCCESS
                    ]);
                }
            }
            \DB::commit();

            if (!empty($ownerId)) {
                $owner = User::find($ownerId);
                if ($owner) {
                    \Notification::send($owner, new SearchFoundOwner($findSession));
                }
            }

            if (!empty($renterId)) {
                $renter = User::find($renterId);
                if ($renter) {
                    \Notification::send($renter, new SearchFoundRenter($findSession));
                }
            }

            $message = Message::query()
                ->where('request_confirm_id', $requestConfirmId)
                ->first();
            if ($message) {
                $pusher = \PusherService::getClient();
                $retVal = Functions::getMessageArr($message);
                $userTrigger = $message->conversation->users()
                    ->where('users.id', '<>', $this->user->id)
                    ->first();


                $pusher->trigger('chat-v2-' . $this->user->id, 'v2-new-message', $retVal);
                if ($userTrigger) {
                    $pusher->trigger('chat-v2-' . $userTrigger->id, 'v2-new-message', $retVal);
                }
            }
        } catch (\Exception $exception) {
            \DB::rollBack();

            return response([
                'status' => 0,
                'message' => 'Có lỗi xảy ra'
            ]);
        }

        return response([
            'status' => 1,
            'message' => 'Thành công'
        ]);


    }

    /**
     * @api {post} /archive Archive cuộc hội thoại
     * @apiName archive
     * @apiGroup conversation
     * @apiDescription Archive cuộc hội thoại
     * @apiParam {String} id
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function archive(Request $request)
    {
        $conversationId = $request->input('id');
        $item = Conversation::find($conversationId);
        if (!$item) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }
        $item->status = Conversation::ARCHIVED;
        $item->save();

        return response([
            'status' => 1
        ]);
    }

    /**
     * @api {get} /count-unread-message Đếm số tin nhắn chưa đọc
     * @apiName count-unread-message
     * @apiGroup conversation
     * @apiDescription Đếm số tin nhắn chưa đọc
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function countUnreadConversation(Request $request)
    {
        $userId = $this->user->id;
        $conversationIds = Conversation::query()
            ->where(function ($q) {
                $q->orWhereNull('status');
                $q->orWhere('status', '<>', Conversation::ARCHIVED);
            })
            ->whereHas('users', function ($q) {
                $q->where('users.id', $this->user->id);
            })
            ->pluck('id')
            ->toArray();
        $cnt = MessageRead::query()
            ->whereIn('conversation_id', $conversationIds)
            ->where('user_id', $userId)
            ->whereNull('read_at')
            ->count();

        return response([
            'status' => 1,
            'data' => $cnt
        ]);
    }

    /**
     * @api {post} /report-sale Báo cáo môi giới
     * @apiName report-sale
     * @apiGroup conversation
     * @apiDescription Báo cáo môi giới
     * @apiParam {String} conversation_id
     * @apiParam {String} hostel_id
     * @apiParam {String} post_crawl_id
     * @apiParam {Array} types Các loại
     * @apiParam {String} content
     *
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function reportSale(Request $request)
    {
        $userId = $this->user->id;
        $conversationId = $request->input('conversation_id');
        $hostelId = $request->input('hostel_id');
        $content = $request->input('content');
        $types = $request->input('types');
        $hostelPostCrawlId = $request->input('post_crawl_id');

        $conversation = Conversation::find($conversationId);
        $owner = null;
        if ($conversation) {
            $owner = $conversation->users()
                ->where('users.id', '<>', $userId)
                ->first();
        } else {
            if (!empty($hostelId)) {
                $hostel = Hostel::find($hostelId);
                if ($hostel) {
                    $owner = $hostel->owner;
                }
            }
        }

        $sale = ReportSale::create([
            'user_id' => $userId,
            'conversation_id' => $conversationId,
            'owner_id' => !empty($owner) ? $owner->id : null,
            'content' => $content,
            'hostel_id' => $hostelId,
            'hostel_post_crawl_id' => $hostelPostCrawlId
        ]);

        if (is_array($types)) {
            foreach ($types as $type) {
                ReportSaleType::create([
                    'report_sale_id' => $sale->id,
                    'type' => $type
                ]);
            }
        }


        return response([
            'status' => 1,
            'message' => 'Success'
        ]);
    }

}
