<?php

namespace App\Http\Controllers;

use App\Models\Conversation;
use App\Models\Message;
use App\Models\MessageStatus;
use App\Models\Participant;
use App\Models\Upload;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class ChatController extends Controller{
    
    public function send_message(Request $request){ 
        $validator = Validator::make($request->all(),[
            'content_type' => 'required|in:text,file',
            'content'      => 'required',
            'to_user_id'   => 'required_without:conversation_id|nullable|exists:users,id',
            'conversation_id' => 'nullable|exists:conversations,id'
        ]);

        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => $validator->errors()
            ]);
        }
        DB::beginTransaction();
        try{
            //check conversation is available? if not create -------direct conversation only
            if($request->has('conversation_id') && $request->conversation_id == ""){
                $conversation = new Conversation;
                $conversation->type = 'direct';
                $conversation->save();
    
                $participant = new Participant;
                $participant->conversation_id = $conversation->id;
                $participant->user_id         = Auth::user()->id;
                $participant->save();
    
                //create to_user_id
                $participant = new Participant;
                $participant->conversation_id = $conversation->id;
                $participant->user_id         = $request->to_user_id;
                $participant->save();
            }else{
                $conversation = Conversation::find($request->conversation_id);
            }
            if($request->content_type == 'file'){
                $folder = public_path('uploads/all');
                if(!is_dir($folder)){
                    mkdir($folder, 0777, true);
                }
                $file = $request->file('content');
                $file_original_name = $file->getClientOriginalName();
                $file_name          = md5(time().rand(0,9999)).'.'.$file->getClientOriginalExtension();
                $file_size          = $file->getSize();
                $extension          = $file->getClientOriginalExtension();
                $type               = get_file_type($extension);
                $file->move($folder, $file_name);
                $upload = new Upload();
                $upload->file_original_name = $file_original_name;
                $upload->file_name          = $file_name;
                $upload->file_size          = $file_size;
                $upload->extension          = $extension;
                $upload->type               = $type;
                $upload->user_id            = Auth::user()->id;
                $upload->save();
                $content = $upload->id;
            }else{
                $content = $request->content;
            }
           
            $message = new Message;
            $message->conversation_id = $request->conversation_id ? $request->conversation_id : $conversation->id;
            $message->user_id         = Auth::user()->id;
            $message->content_type    = $request->content_type;
            $message->content         = $content;
            $message->sent_at         = now();
            $message->save();

            //update message status
            $participants = Participant::where('conversation_id', $request->conversation_id ? $request->conversation_id : $conversation->id)->where('user_id', '!=', Auth::user()->id)->get();
            if(!empty($participants)){
                foreach($participants as $participant){
                    $message_status = new MessageStatus();
                    $message_status->message_id = $message->id;
                    $message_status->user_id    = $participant->user_id;
                    $message_status->delivery_status = 'delivered';
                    $message_status->delivered_at    = now();
                    $message_status->save();
                }
            }
            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Message sent successfully',
            ]);
        }catch(\Exception $e){
            DB::rollBack();

            return response()->json([
                'status' => false,
                'message' => $e->getMessage()
            ]);
        }
        
    }

    public function conversation_list(Request $request){
        $direct_conversations = Participant::select('participants.*')->whereRaw('participants.conversation_id IN (SELECT conversation_id FROM participants WHERE user_id = ?)', [Auth::user()->id])
                                     ->where('participants.user_id', '!=', Auth::user()->id)
                                     ->join('conversations', 'participants.conversation_id', '=', 'conversations.id')
                                     ->where('conversations.type', '=', 'direct')
                                     ->get();
        $group_conversation   = Conversation::select('conversations.id as conversation_id', 'conversations.type', 'conversations.name')->where('type', '=', 'group')->get();
                                            
                                           
        $conversations        = $direct_conversations->merge($group_conversation);
                            
        if($conversations->count() > 0){
            foreach($conversations as $conversation){
                $lastmessage = Message::where('conversation_id', $conversation->conversation_id)
                                      ->orderBy('sent_at', 'desc')
                                      ->first();
                $content = "";
                $user_id = "";
                $user_name = "";
                $profile_picture = "";
                if(!empty($lastmessage)){
                    if($lastmessage->content_type == "text"){
                        $content = $lastmessage->content;
                    }else{
                        $content = uploaded_asset($lastmessage->content);
                    }
                    //if type is group then get last message user else get receiver user
                    if($conversation->type == "group"){
                        $user_id = $lastmessage->user_id;
                        $user_name = $lastmessage->user->name;
                        $profile_picture = $lastmessage->user->profile_picture;
                    }else{
                        $user_id = $conversation->user_id;
                        $user_name = $conversation->user ? $conversation->user->name : "";
                        $profile_picture = $conversation->user ? $conversation->user->profile_picture : "";
                    }
                }
                $data[] = array(
                    'user_id'   => $user_id,
                    'user_name' => $user_name,
                    'type'      => $conversation->type == "group" ? "group" : "direct",
                    'Group_name' => $conversation->type == "group" ? $conversation->name : "",
                    'profile_picture' => $profile_picture,
                    'conversation_id' => $conversation->conversation_id,
                    'content_type'    => $lastmessage ? $lastmessage->content_type : "",
                    'content'         => $content,
                    'sent_at'         => $lastmessage ? $lastmessage->sent_at : "",
                );
            }     
            
            return response()->json([
                'status' => true,
                'data' => $data
            ]);
        }else{
            return response()->json([
                'status' => false,
                'message' => 'No conversation found'
            ]);
        }
    }

    public function create_group(Request $request){
        $validator = Validator::make($request->all(),[
            'name' => 'required|unique:conversations,name',
            'participants' => 'required'
        ]);

        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => $validator->errors()
            ]);
        }
        DB::beginTransaction();
        try{
            if($request->has('participants') && count($request->participants) > 0){
                //create conversation
                $conversation = new Conversation;
                $conversation->type = 'group';
                $conversation->name = $request->name;
                $conversation->save();
                //create participants
                foreach($request->participants as $user){
                    $participant = new Participant;
                    $participant->conversation_id = $conversation->id;
                    $participant->user_id         = $user;
                    $participant->save();
                }
                DB::commit();

                return response()->json([
                    'status' => true,
                    'message' => 'Group created successfully'
                ]);
            }
                
                
        }catch(\Exception $e){
                DB::rollBack();
                
                return response()->json([
                    'status' => false,
                    'message' => $e->getMessage()
                ]);
        }
        
    }

    public function update_as_read(Request $request){
        $validator = Validator::make($request->all(),[
            'message_id' => 'required'
        ]);

        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => $validator->errors()
            ]);
        }
        if($request->has('message_id') && count($request->message_id) > 0){
            foreach($request->message_id as $message_id){
                $message = MessageStatus::where('message_id', $request->message_id)->first();
                if($message && $message->user_id == auth()->id()){
                    $message->read_status = 'read';
                    $message->read_at     = now();
                    $message->save();
                }
            }

            return response()->json([
                'status' => true,
                'message' => 'Message marked as read'
            ]);
        }else{
            return response()->json([
                'status' => false,
                'message' => 'No message found'
            ]);
        }
        
    }

    public function participants_list(Request $request,$id){
        if($id != ""){
            $participants = Participant::where('conversation_id', $id)->with('user')->get();
            if(!empty($participants)){
                return response()->json([
                    'status' => true,
                    'participants' => $participants
                ]);
            }else{
                return response()->json([
                    'status' => false,
                    'message' => 'No participants found'
                ]);
            }
        }else{
            return response()->json([
                'status' => false,
                'message' => 'No conversation found'
            ]);
        }
    }

    public function add_participants(Request $request){
        $validator = Validator::make($request->all(),[
            'conversation_id' => 'required|exists:conversations,id',
            'participants' => 'required'
        ]);

        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => $validator->errors()
            ]);
        }
        DB::beginTransaction();
        try{
            if($request->has('participants') && count($request->participants) > 0){
                foreach($request->participants as $user){
                    $member = Participant::where('conversation_id', $request->conversation_id)->where('user_id', $user)->first();
                    $_user = User::where('id', $user)->first();
                    if(empty($member) && !empty($_user)){
                        $participant = new Participant;
                        $participant->conversation_id = $request->conversation_id;
                        $participant->user_id         = $user;
                        $participant->save();
                    }
                }
                DB::commit();
                return response()->json([
                    'status' => true,
                    'message' => 'Participants added successfully'
                ]);
            }
        }catch(\Exception $e){
            DB::rollBack();
            return response()->json([
                'status' => false,
                'message' => $e->getMessage()
            ]);
        }
    }

    public function explore_conversations(Request $request,$id){
        if($id){
           $messages = Message::where('conversation_id', $id)->with('user')->paginate(20);
           if(!empty($messages)){
               //modify message content based on content type
               $messages->getCollection()->transform(function($message){
                    if($message->content_type == 'text'){
                        $message->content = $message->content;
                    }else{
                        $message->content = uploaded_asset($message->content);
                    }
                    return $message;
               });
               return response()->json([
                   'status' => true,
                   'messages' => $messages
               ]);
           }   else{
               return response()->json([
                   'status' => false,
                   'message' => 'No messages found'
               ]);
           }
        }else{
            return response()->json([
                'status' => false,
                'message' => 'No conversation found'
            ]);
        }
    }

}
