<?php

namespace App\Http\Controllers;

use App\Events\NewMessage;
use App\Events\UserSendMessageEvent;
use App\Events\TypingMessageEvent;
use App\Events\SeenMessageEvent;
use App\UserConversation;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Pagination\LengthAwarePaginator;
use App\Http\Resources\MessageResource;
use App\Conversation;
use App\Message;

class ChatController extends Controller
{
	const ITEM_PER_PAGE = 20;
	private $user;
	
	public function __construct()
	{
		$this->user = null;
		if (auth('api')->check()) $this->user = auth('api')->user();
	}
	
	public function index(Request $request)
	{
		$params = $request->all();
		$limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
		$conversionId = Arr::get($params, 'conversion_id', 0);
		$lastId = Arr::get($params, 'last_id', null);
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		$checkUser = UserConversation::where('conversation_id', $conversionId)
			->where('user_id', $this->user->id)
			->count();
		
		if ($checkUser <= 0) {
			return response()->json(['error' => 'Conversation not found'], 403);
		}
		
		$query = Message::where('conversation_id', $conversionId)->orderBy('id', 'desc');
		if ($lastId) $query->where('id', '<', $lastId);
		$messages = $query->take($limit)->get();
		$total = Message::where('conversation_id', $conversionId)->count();
		$paginator = new LengthAwarePaginator($messages, $total, $limit, null, ['path' => $request->url()]);
		
		return MessageResource::collection($paginator);
	}
	
	public function checkMessage()
	{
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		// Check if user has any conversations with unread messages (not sent by themselves)
		$hasNewMessageBadge = Conversation::whereExists(function ($query) {
			$query->select('id')
				->from('user_conversations')
				->whereColumn('conversations.id', 'user_conversations.conversation_id')
				->where('user_conversations.user_id', $this->user->id);
		})
			->whereExists(function ($query) {
				$query->select('id')
					->from('messages')
					->whereColumn('messages.conversation_id', 'conversations.id')
					->where('messages.sender_id', '!=', $this->user->id)
					->where('messages.is_read', false);
			})
			->exists();
		
		return response()->json([
			'status'          => 'success',
			'has_new_message' => $hasNewMessageBadge
		], 200);
	}
	
	public function getUnreadCount()
	{
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		// Count conversations where user has unread messages (not sent by themselves)
		$unreadCount = Conversation::whereExists(function ($query) {
			$query->select('id')
				->from('user_conversations')
				->whereColumn('conversations.id', 'user_conversations.conversation_id')
				->where('user_conversations.user_id', $this->user->id);
		})
			->whereExists(function ($query) {
				$query->select('id')
					->from('messages')
					->whereColumn('messages.conversation_id', 'conversations.id')
					->where('messages.sender_id', '!=', $this->user->id)
					->where('messages.is_read', false);
			})
			->count();
		
		return response()->json([
			'status'       => 'success',
			'unread_count' => $unreadCount
		], 200);
	}
	
	public function store(Request $request)
	{
		$request->validate([
			'conversion_id' => 'required',
			'content'       => 'required|string|max:1000',
			'content_type'  => 'required|in:text,image,file'
		]);
		
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		$params = $request->all();
		$conversionId = $params['conversion_id'];
		
		$checkUserConversation = UserConversation::where('conversation_id', $conversionId)
			->where('user_id', $this->user->id)
			->first();
		
		if (!$checkUserConversation) return response()->json(['error' => 'Conversation not found'], 403);
		
		$conversation = Conversation::where('id', $conversionId)->first();
		
		$params = $request->all();
		$message = new Message();
		$message->conversation_id = $conversation->id;
		$message->sender_id = $this->user->id;
		$message->type = 'sender';
		$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();
		$message->save();
		
		$conversation->update([
			'has_new'               => true,
			'has_new_message_badge' => true,
			'last_message_at'       => now()
		]);
		broadcast(new NewMessage($message->load(['conversation', 'sender'])))->toOthers();
		broadcast(new UserSendMessageEvent($conversation))->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 seenMessage(Request $request)
	{
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		$conversationId = $request->input('conversation_id');
		
		// If no conversation_id provided, mark all messages as read for user
		if (!$conversationId) {
			// Mark all unread messages as read for user's conversations
			Message::whereExists(function ($query) {
				$query->select('id')
					->from('user_conversations')
					->whereColumn('messages.conversation_id', 'user_conversations.conversation_id')
					->where('user_conversations.user_id', $this->user->id);
			})
				->where('sender_id', '!=', $this->user->id)
				->where('is_read', false)
				->update(['is_read' => true, 'read_at' => now()]);
			
			return response()->json(['status' => 'success'], 200);
		}
		
		$checkUser = UserConversation::where('conversation_id', $conversationId)
			->where('user_id', $this->user->id)
			->first();
		
		if (!$checkUser) {
			return response()->json(['error' => 'Conversation not found'], 403);
		}
		
		// Mark all unread messages in this conversation as read
		$messages = Message::where('conversation_id', $conversationId)
			->where('sender_id', '!=', $this->user->id)
			->where('is_read', false)
			->get();
		
		if ($messages->count() > 0) {
			// Update all messages as read
			Message::where('conversation_id', $conversationId)
				->where('sender_id', '!=', $this->user->id)
				->where('is_read', false)
				->update(['is_read' => true, 'read_at' => now()]);
				
			// Only broadcast SeenMessageEvent for the last message to reduce system load
			$lastMessage = $messages->sortByDesc('created_at')->first();
			if ($lastMessage) {
				$lastMessage->refresh(); // Refresh to get updated is_read status
				broadcast(new SeenMessageEvent($lastMessage->load(['conversation', 'sender'])))->toOthers();
			}
		}
		
		return response()->json(['status' => 'success'], 200);
	}
	
	public function typingMessage(Request $request)
	{
		if (!$this->user) return response()->json(['error' => 'User not found'], 403);
		
		$conversationId = $request->input('conversation_id');
		if (!$conversationId) {
			return response()->json(['error' => 'Conversation ID required'], 400);
		}
		
		$checkUser = UserConversation::where('conversation_id', $conversationId)
			->where('user_id', $this->user->id)
			->first();
		
		if (!$checkUser) {
			return response()->json(['error' => 'Conversation not found'], 403);
		}
		
		broadcast(new TypingMessageEvent($this->user->id, $conversationId))->toOthers();
		
		return response()->json(['status' => 'success'], 200);
	}
	
}
