<?php

namespace App\Http\Controllers\Admin;

use App\Events\SeenMessageEvent;
use App\Events\TypingMessageEvent;
use App\Events\UserTypingEvent;
use App\Http\Controllers\Controller;
use App\Laravue\Models\User;
use App\UserConversation;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Pagination\LengthAwarePaginator;
use App\Http\Resources\Admin\ConversationResource;
use App\Http\Resources\Admin\MessageResource;
use App\Events\NewMessage;
use App\Conversation;
use App\Message;

/**
 * Class ChatController
 *
 * @package App\Http\Controllers
 */
class ChatController extends Controller
{
	const ITEM_PER_PAGE = 20;
	private $userId;
	
	public function __construct()
	{
		$this->userId = auth('api')->user()->id;
	}
	
	public function show($id)
	{
		$conversation = Conversation::where('id', $id)->first();
		if (!isset($conversation)) return response()->json(['errors' => 'Conversation is not valid'], 403);
		
		/*$userId = auth()->user()->id;
		$checkUser = UserConversation::where('conversation_id', $conversation->id)
			->where('user_id', $userId)
			->count();
		
		if ($checkUser == 0) {
			UserConversation::create([
				'conversation_id' => $conversation->id,
				'user_id'         => $userId
			]);
		}*/
		
		return new ConversationResource($conversation);
	}
	
	public function getConversations(Request $request)
	{
		$params = $request->all();
		$limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
		
		$userConversationsList = UserConversation::where('user_id', $this->userId)->pluck('conversation_id')->toArray();
		$conversations = Conversation::with(['lastMessage', 'user'])
			->whereIn('id', $userConversationsList)
			->orderBy('last_message_at', 'desc');
		
		return ConversationResource::collection($conversations->paginate($limit));
	}
	
	public function getMessages(Request $request, $conversationId)
	{
		$params = $request->all();
		$limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
		$lastId = Arr::get($params, 'last_id', null);
		
		$checkUser = UserConversation::where('conversation_id', $conversationId)
			->where('user_id', $this->userId)
			->count();
		
		$total = 0;
		if ($checkUser > 0) {
			$query = Message::where('conversation_id', $conversationId)->orderBy('id', 'desc');
			if ($lastId) $query->where('id', '<', $lastId);
			$messages = $query->take($limit)->get();
			$total = Message::where('conversation_id', $conversationId)->count();
		} else {
			$messages = Message::where('id', 0)->orderBy('id', 'desc')->get();
		}
		
		$paginator = new LengthAwarePaginator($messages, $total, $limit, null, ['path' => $request->url()]);
		
		return MessageResource::collection($paginator);
	}
	
	public function sendMessage(Request $request)
	{
		$request->validate([
			'conversation_id' => 'required|exists:conversations,id',
			'content'         => 'required|string|max:1000',
			'content_type'    => 'required|in:text,image,file'
			/*'file'            => 'nullable|file|mimes:jpeg,png,jpg|max:2048',*/
		]);
		
		$params = $request->all();
		$message = new Message();
		$message->conversation_id = $params['conversation_id'];
		$message->sender_id = auth('api')->id();
		$message->type = 'receiver';
		$message->content = $params['content'];
		$message->content_type = $params['content_type'];
		$message->file_path = $params['file_path'] ?? null;
		$message->is_read = false;
		$message->created_at = now()->toDateTimeString();
		$message->updated_at = now()->toDateTimeString();
		
		/*if ($request->hasFile('file')) {
			$path = $request->file('file')->store('chat_images', 'public');
			$message->file_path = $path;
		}*/
		$message->save();
		
		Conversation::where('id', $request->conversation_id)->update([
			'has_new_message_badge' => true,
			'last_message_at'       => now()
		]);
		broadcast(new NewMessage($message->load(['conversation', 'sender'])))->toOthers();
		
		return response()->json([
			'status'       => 'success',
			'id'           => $message->id,
			'type'         => $message->type,
			'content_type' => $message->content_type,
			'is_read'      => $message->is_read,
			'created_at'   => $message->created_at
		]);
	}
	
	public function sendMessageFiles(Request $request)
	{
		$request->validate([
			'conversation_id' => 'required|exists:conversations,id',
			'content_type'    => 'required|in:image,file',
			'files'           => 'required|file|mimes:jpeg,jpg,png,gif,pdf,doc,docx,xls,xlsx|max:10240',
		]);
	}
	
	public function searchMessages(Request $request)
	{
		$request->validate([
			'query'           => 'required|string',
			'date_from'       => 'nullable|date',
			'date_to'         => 'nullable|date',
			'conversation_id' => 'nullable|exists:conversations,id'
		]);
		
		$query = Message::with('sender', 'conversation')
			->where('content', 'LIKE', "%{$request->query}%");
		
		if ($request->date_from) {
			$query->whereDate('created_at', '>=', $request->date_from);
		}
		
		if ($request->date_to) {
			$query->whereDate('created_at', '<=', $request->date_to);
		}
		
		if ($request->conversation_id) {
			$query->where('conversation_id', $request->conversation_id);
		}
		
		$messages = $query->orderBy('created_at', 'desc')->paginate(20);
		
		return response()->json($messages);
	}
	
	public function getOrCreateConversation($userId)
	{
		$user = User::findOrFail($userId);
		$userConversationList = UserConversation::where('user_id', $user->id)->pluck('conversation_id')->toArray();
		$userConversationList2 = UserConversation::where('user_id', $this->userId)->pluck('conversation_id')->toArray();
		$conversationId = null;
		foreach ($userConversationList as $cId) {
			if (in_array($cId, $userConversationList2)) {
				$conversationId = $cId;
				break;
			}
		}
		
		if ($conversationId != null) {
			$conversation = Conversation::where('id', $conversationId)->first();
		} else {
			$conversation = Conversation::create([
				'user_id' => $userId,
				'title'   => $user->name
			]);
			UserConversation::create([
				'conversation_id' => $conversation->id,
				'user_id'         => $this->userId
			]);
			UserConversation::create([
				'conversation_id' => $conversation->id,
				'user_id'         => $user->id
			]);
		}
		
		return response()->json($conversation);
	}
	
	public function countConversationNew()
	{
		$conversations = Conversation::where('has_new', true)->pluck('id')->toArray();
		
		return response()->json(['status' => 'success', 'list' => $conversations, 'total' => count($conversations)], 200);
	}
	
	public function resetConversationNew()
	{
		Conversation::where('has_new', true)->update(['has_new' => false]);
		
		return response()->json(null, 204);
	}
	
	public function activeConversation($id = 0)
	{
		$conversation = Conversation::where('id', $id)->first();
		if ($conversation) {
			$conversation->update(['has_new' => false]);
			$user = User::where('id', $conversation->user_id)->first();
			if ($user) {
				$user->update(['is_online' => true, 'last_activity' => now()]);
				$conversation->update(['is_active' => true]);
			} else {
				$conversation->update(['is_active' => false]);
			}
			
			$lastMessage = Message::where('conversation_id', $conversation->id)
				->where('sender_id', '!=', $this->userId)
				->orderBy('created_at', 'desc')
				->first();
			
			if ($lastMessage && !$lastMessage->is_read) {
				$lastMessage->update(['is_read' => true, 'read_at' => now()]);
				broadcast(new SeenMessageEvent($lastMessage->load(['conversation', 'sender'])))->toOthers();
			}
		}
		
		return response()->json(null, 204);
	}
	
	public function typingConversation($id = 0)
	{
		$conversation = Conversation::where('id', $id)->first();
		if ($conversation) {
			broadcast(new TypingMessageEvent($this->userId, $conversation->id))->toOthers();
		}
		
		return response()->json(null, 204);
	}
	
	public function userTyping(Request $request)
	{
		$conversationId = $request->conversation_id;
		$userId = auth('api')->id();
		
		$admins = User::whereHas('roles', function ($query) {
			$query->whereIn('name', ['admin', 'manager']);
		})->get();
		
		foreach ($admins as $admin) {
			broadcast(new UserTypingEvent($userId, $conversationId, $admin->id));
		}
		
		return response()->json(['status' => 'success']);
	}
}
