<?php

namespace App\Models\Chat;

use App\Entities\Chat\ChatMessageEntity;
use App\Models\ChatNotification;
use App\Models\Usuarios\UserModel;
use CodeIgniter\Model;
use CodeIgniter\Database\BaseBuilder;

class ChatMessageModel extends Model
{
    protected $table            = 'chat_messages';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $returnType       = ChatMessageEntity::class;
    protected $useSoftDeletes   = true;
    protected $protectFields    = true;
    protected $allowedFields    = [
        "message",
        "chat_id",
        "sender_id",
        "receiver_id",
        "viewed"
    ];

    protected bool $allowEmptyInserts = false;
    protected bool $updateOnlyChanged = true;

    protected array $casts = [];
    protected array $castHandlers = [];

    // Dates
    protected $useTimestamps = true;
    protected $dateFormat    = 'datetime';
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';
    protected $deletedField  = 'deleted_at';

    // Validation
    protected $validationRules      = [];
    protected $validationMessages   = [];
    protected $skipValidation       = false;
    protected $cleanValidationRules = true;

    // Callbacks
    protected $allowCallbacks = true;
    protected $beforeInsert   = [];
    protected $afterInsert    = ['callbackNewMessage'];
    protected $beforeUpdate   = [];
    protected $afterUpdate    = [];
    protected $beforeFind     = [];
    protected $afterFind      = [];
    protected $beforeDelete   = [];
    protected $afterDelete    = [];

    /**
     * Devuelve los mensajes del chat
     *
     * @param integer $chat_id
     * @return object 
     */
    public function get_chat_messages(int $chat_id): array
    {
        $user = model(UserModel::class);
        $messages = $this->builder()->where("chat_id", $chat_id)->orderBy("created_at", "asc")->get()->getResultObject();
        foreach ($messages as $message) {
            $message->pos = auth()->user()->id == $message->sender_id ? "right" : "left";
            if (auth()->user()->id == $message->sender_id) {
                $message->user = auth()->user();
            } else {
                $message->user = $user->find($message->sender_id);
            }
        }
        return $messages;
    }
    public function get_chat_message(int $chat_message_id): object
    {
        $user = model(UserModel::class);
        $auth_user = auth()->user();
        $message = $this->find($chat_message_id);
        $message->pos = $auth_user->id == $message->sender_id ? "right" : "left";
        if ($auth_user->id == $message->sender_id) {
            $message->sender_first_name = $auth_user->first_name;
            $message->sender_last_name = $auth_user->last_name;
        } else {
            $sender_user = $user->find($message->sender_id);
            $message->sender_first_name = $sender_user->first_name;
            $message->sender_last_name = $sender_user->last_name;
        }
        return $message;
    }
    public function get_chat_contact_messages(int $receiver_id): array
    {
        $conversationArray = [];
        $userModel = model(UserModel::class);
        $chatNotificationModel = model(ChatNotification::class);
        $receiverUser = $userModel->find($receiver_id);
        $chat_id = null;
        $messagesFromClient = $this->builder()
            ->where("sender_id", auth()->user()->id)
            ->where("receiver_id", $receiverUser->id)
            ->get()->getResultObject();
        $messagesFromReceiver = $this->builder()
            ->where("sender_id", $receiver_id)
            ->where("receiver_id", auth()->user()->id)
            ->get()->getResultObject();
        foreach ($messagesFromClient as $message) {
            $message->pos = "right";
            $message->user = auth()->user();
            $conversationArray[] = $message;
        }
        foreach ($messagesFromReceiver as $message) {
            $message->pos = "left";
            $message->user = $receiverUser;
            $conversationArray[] = $message;
        }
        $dates = array();

        foreach ($conversationArray as $key => $row) {
            $chatNotificationModel->builder()->set("viewed", true)->where("chat_message_id", $row->id)->where("user_id", auth()->user()->id)->update();
            $dates[$key] = strtotime($row->created_at);
        }
        array_multisort($dates, SORT_ASC, $conversationArray);
        return $conversationArray;
    }

    public function get_chat_unread_messages_count(int $sender_id): int
    {
        $messagesFromReceiver = $this->builder()
            ->where("sender_id", $sender_id)
            ->where("viewed", false)
            ->where("receiver_id", auth()->user()->id)->countAllResults();
        return $messagesFromReceiver;
    }
    public function get_chat_department_messages_count(int $chat_id): int
    {
        $chatDepartmentMessagesCount = $this->builder()
            ->where("id", $chat_id)
            ->countAllResults();
        return $chatDepartmentMessagesCount;
    }
    public function get_chat_messages_count(int $sender_id): int
    {
        $messagesFromReceiver = $this->builder()
            ->groupStart()
            ->where("sender_id", $sender_id)
            ->where("receiver_id", auth()->user()->id)
            ->orGroupStart()
            ->where("receiver_id", $sender_id)
            ->where("sender_id", auth()->user()->id)
            ->groupEnd()
            ->groupEnd()
            ->countAllResults();
        return $messagesFromReceiver;
    }
    public function set_chat_messages_as_read(int $sender_id): int
    {
        $messagesFromReceiver = $this->builder()
            ->set("viewed", true)
            ->where("user_id", $sender_id)
            ->where("receiver_id", auth()->user()->id)->update();
        return $messagesFromReceiver;
    }
    public function set_chat_department_messages_as_read(int $chat_id): int
    {
        $chatDepartmentModel = model(ChatDeparmentModel::class);
        $chatModel = model(ChatModel::class);
        $messagesFromReceiver = 0;
        $auth_user = auth()->user();
        $chat_department_id = $chatModel->find($chat_id)->chat_department_id;
        $users_in_chat = array_map(fn($x) => $x->id, $chatDepartmentModel->getChatDepartmentUsers($chat_department_id));
        if (auth()->user()->cliente_id) {
            // Si el usuario es cliente, marca como leídos todos los mensajes exceptos los suyos
            $messagesFromReceiver = $this->builder()
                ->set("viewed", true)
                ->where("chat_id", $chat_id)
                ->whereNotIn("sender_id", [$auth_user->id])->update();
        } else {
            // Si el usuario no es cliente y está dentro de los usuarios de departamento
            // marca como leido todos los mensajes, excepto los mensajes de los usuarios 
            // de dentro del departamento
            if (in_array($auth_user->id, $users_in_chat) == true) {
                // if (($key = array_search($auth_user->id, $users_in_chat)) !== false) {
                //     unset($users_in_chat[$key]);
                // }
                $messagesFromReceiver = $this->builder()
                    ->set("viewed", true)
                    ->where("chat_id", $chat_id)
                    ->whereNotIn("sender_id", $users_in_chat)
                    ->update();
            }
        }

        return $messagesFromReceiver;
    }
    public function callbackNewMessage(array $data)
    {
        $authUser = auth()->user();
        $chatNotificationModel = model(ChatNotification::class);
        $chatMessageEntity = $this->find($data["id"]);
        $chatEntity = $chatMessageEntity->chat();
        if ($chatEntity->chat_department_id) {
            $chatDepartmentEntity = $chatEntity->department();
            $adminUsers = $chatDepartmentEntity->chatDepartmentAdminUsers();
            $modelFk = $chatEntity->relatedFk();
            $externalUsers = $chatDepartmentEntity->chatDepartmentExternalUsers($modelFk["relatedFkValue"], $modelFk["relatedModel"]);
            if ($modelFk["relatedModel"] && $modelFk["relatedFkValue"]) {

                foreach ($adminUsers as $user) {
                    if ($user->user_id != $authUser->id) {
                        $chatNotificationModel->insert([
                            "user_id" => $user->user_id,
                            "chat_message_id" => $data["id"]
                        ]);
                    }
                }
                foreach ($externalUsers as $user) {
                    if ($user->user_id != $authUser->id) {
                        $chatNotificationModel->insert([
                            "user_id" => $user->user_id,
                            "chat_message_id" => $data["id"]
                        ]);
                    }
                }
            }
        }else{
            foreach ($chatEntity->internalUsers() as $user) {
                if ($user->user_id != $authUser->id) {
                    $chatNotificationModel->insert([
                        "user_id" => $user->user_id,
                        "chat_message_id" => $data["id"]
                    ]);
                }
            }
        }
        return $data;
    }
}
