<?php

namespace App\Services;

use App\Controllers\Configuracion\ConfigVariables;
use App\Entities\Chat\ChatEntity;
use App\Entities\Chat\ChatMessageEntity;
use App\Entities\Chat\ChatNotificationEntity;
use App\Entities\Clientes\ClienteContactoEntity;
use App\Entities\Usuarios\UserEntity;
use App\Models\Chat\ChatDeparmentModel;
use App\Models\Chat\ChatDeparmentUserModel;
use App\Models\Chat\ChatMessageModel;
use App\Models\Chat\ChatModel;
use App\Models\ChatNotification;
use App\Models\ChatUser;
use App\Models\Clientes\ClienteContactoModel;
use App\Models\Configuracion\ConfigVariableModel;
use App\Models\Presupuestos\PresupuestoModel;
use App\Models\Usuarios\UserModel;
use CodeIgniter\Config\BaseService;
use App\Services\EmailService;
use Exception;

class ChatService extends BaseService
{
    protected ?ChatEntity $chatEntity;
    protected EmailService $emailService;
    protected UserModel $userModel;
    protected ChatModel $chatModel;
    protected ChatMessageModel $chatMessageModel;
    protected ChatUser $chatUserModel;
    protected ChatNotification $chatNotificationModel;
    protected PresupuestoModel $presupuestoModel;
    protected ChatDeparmentModel $chatDepartmentModel;
    protected ChatDeparmentUserModel $chatDepartmentUserModel;
    protected ClienteContactoModel $clienteContactoModel;
    protected ConfigVariableModel $configVariables;
    protected array $modelFkMap = [
        "presupuesto" => "presupuesto_id",
        "pedido" => "pedido_id",
        "factura" => "factura_id",
        "ot" => "orden_trabajo_id"
    ];
    protected array $modelClassMap;
    public function __construct()
    {
        $this->emailService = service('emailService');  // Usar el servicio de email de Safekat y no el de CI4
        $this->userModel = model(UserModel::class);
        $this->chatModel = model(ChatModel::class);
        $this->clienteContactoModel = model(ClienteContactoModel::class);
        $this->chatMessageModel = model(ChatMessageModel::class);
        $this->chatNotificationModel = model(ChatNotification::class);
        $this->chatDepartmentUserModel = model(ChatDeparmentUserModel::class);
        $this->chatUserModel = model(ChatUser::class);
        $this->presupuestoModel = model(PresupuestoModel::class);
        $this->chatDepartmentModel = model(ChatDeparmentModel::class);
        $this->configVariables = model(ConfigVariableModel::class);
    }
    public function setChat($chatEntity): self
    {
        $this->chatEntity = $chatEntity;
        return $this;
    }
    public function storeChatMessage(string $chatDepartmentId, string $model, int $modelId, array $data): ?ChatMessageEntity
    {
        $this->chatEntity = $this->chatModel->where('chat_department_id', $chatDepartmentId)->where($this->modelFkMap[$model], $modelId)->first();
        if ($this->chatEntity == null) {
            $chatId = $this->createChat($chatDepartmentId, $model, $modelId);
            $this->chatEntity = $this->chatModel->find($chatId);
        }
        if ($data["client"]) {
            $cliente_contacto = $this->clienteContactoModel->find($data["client"]);
            if ($cliente_contacto) {
                $userClienteContacto = $cliente_contacto->cliente()->user();
                if ($userClienteContacto) {
                    $cliente_in_department = $this->chatDepartmentUserModel
                        ->where('chat_department_id', $chatDepartmentId)
                        ->where('user_id', $userClienteContacto->id)
                        ->where($this->modelFkMap[$model], $modelId)
                        ->first();
                    if ($cliente_in_department == null) {
                        $this->chatDepartmentUserModel->insert(['chat_department_id' => $chatDepartmentId, 'user_id' => $userClienteContacto->id, $this->modelFkMap[$model] => $modelId]);
                    }
                }
            }
        }
        $userAdminDepartment = $this->chatDepartmentUserModel
            ->where('chat_department_id', $data["chat_department_id"])
            ->where('user_id', auth()->user()->id)
            ->where("pedido_id", null)
            ->where("factura_id", null)
            ->where("presupuesto_id", null)
            ->first();
        $userAlreadyInDepartment = $this->chatDepartmentUserModel
            ->where('chat_department_id', $data["chat_department_id"])
            ->where('user_id', auth()->user()->id)
            ->where($this->modelFkMap[$model], $modelId)
            ->first();
        if ($userAdminDepartment == null && $userAlreadyInDepartment == null) {
            $this->chatDepartmentUserModel->insert(['chat_department_id' => $data["chat_department_id"], $this->modelFkMap[$model] => $modelId, 'user_id' => auth()->user()->id]);
        }
        $chat_message_id = $this->chatMessageModel->insert(["chat_id" => $this->chatEntity->id, "sender_id" => auth()->user()->id, "message" => $data["message"]]);
        $chatMessageEntity = $this->chatMessageModel->find($chat_message_id);
        if ($data["client"]) {
            $cliente_contacto = $this->clienteContactoModel->find($data["client"]);
            if ($cliente_contacto) {
                $this->sendMessageNotificationToClienteContacto($chatMessageEntity, $cliente_contacto);
            }
        }
        return $chatMessageEntity;
    }
    public function createChat(int $chatDepartmentId, string $model, int $modelId): bool|int|string
    {
        $r = false;
        switch ($model) {
            case 'presupuesto':
                $r = $this->chatModel->createChatPresupuesto($chatDepartmentId, $modelId);
                break;
            case 'pedido':
                $r = $this->chatModel->createChatPedido($chatDepartmentId, $modelId);
                break;
            case 'factura':
                $r = $this->chatModel->createChatFactura($chatDepartmentId, $modelId);
                break;
            case 'ot':
                $r = $this->chatModel->createChatOrdenTrabajo($chatDepartmentId, $modelId);
                break;
            default:
                break;
        }
        return $r;
    }

    public function getChatDepartments(string $model, int $modelId): array
    {
        $chatDepartments = $this->chatDepartmentModel->getModelChatDepartments($this->modelFkMap[$model], $modelId);
        $departmentWithChat = array_map(fn($q) => $q["name"], $chatDepartments);
        if (count($departmentWithChat) > 0) {
            $departmentWithoutChat = $this->chatDepartmentModel->whereNotIn('name', $departmentWithChat)->findAll();
        } else {
            $departmentWithoutChat = $this->chatDepartmentModel->findAll();
        }
        foreach ($departmentWithoutChat as $value) {
            $d = [];
            $d["id"] = $value->id;
            $d["name"] = $value->name;
            $d["display"] = $value->display;
            $d["countMessages"] = "0";
            $chatDepartments[] = $d;
        }
        return $chatDepartments;
    }

    public function storeHebra(string $model, int $modelId, array $data): bool
    {
        $auth_user = auth()->user();
        $chatId = $this->chatModel->insert([$this->modelFkMap[$model] => $modelId, 'title' => $data['title']]);

        if (isset($data["users"])) {
            $data["users"][] = $auth_user->id;
            $chatUserData = array_map(fn($x) => ["user_id" => $x, "chat_id" => $chatId], $data["users"]);
            $this->chatUserModel->insertBatch($chatUserData);
        }
        $this->chatMessageModel->insert(
            [
                'chat_id' => $chatId,
                'message' => $data['message'],
                'sender_id' => $auth_user->id
            ]
        );
        return true;
    }

    public function getHebras(string $model, int $modelId): array
    {
        $chats = $this->chatModel->where('chat_department_id', null)
            ->where($this->modelFkMap[$model], $modelId)
            ->findAll();
        foreach ($chats as $c) {
            $this->chatModel->setAsViewedChatUserNotifications($c->id, auth()->user()->id);
        }
        $chatWithHebraData = array_map(fn(ChatEntity $c) => $c->withHebra(), $chats);
        return $chatWithHebraData ?? [];
    }
    public function getAuthUserNotifications(): array
    {
        $departmentNotifications = $this->chatModel->getChatDepartmentNotifications();
        $internalNotifications = $this->chatModel->getChatInternalNotifications();
        $totalMessages = 0;
        $countNotificiationDepartments = array_map(fn($n) => $n->unreadMessages, $departmentNotifications);
        $countNotificationInternal = array_map(fn($n) => $n->unreadMessages, $internalNotifications);
        $totalMessages = array_sum($countNotificiationDepartments) + array_sum($countNotificationInternal);

        return [
            "departmentNotifications" => $departmentNotifications,
            "internalNotifications" => $internalNotifications,
            "totalMessages" => $totalMessages
        ];
    }
    public function sendMessageNotificationEmail(ChatMessageEntity $chatMessageEntity, UserEntity $user): bool
    {
        $users = auth()->getProvider();
        $toEmail = $users->find($user->id)->getEmail();

        $subject = '[Safekat]' . lang('Chat.mail.mail_subject') . ' - ' . $chatMessageEntity->chat()->title;

        $message = view('themes/vuexy/mail/messageNotification', [
            "header" => lang('Chat.mail.mail_subject'),
            "data" => $chatMessageEntity->withUser(),
        ]);

        return $this->emailService->send($subject, $message, $toEmail);
    }
    public function sendMessageNotificationToClienteContacto(ChatMessageEntity $chatMessageEntity, ClienteContactoEntity $clienteContacto): bool
    {
        $users = auth()->getProvider();
        $toEmail = $clienteContacto->email;

        $subject = '[Safekat]' . lang('Chat.mail.mail_subject') . ' - ' . $chatMessageEntity->chat()->title;

        $message = view('themes/vuexy/mail/messageNotificationClienteContacto', [
            "header" => lang('Chat.mail.mail_subject'),
            "contacto" => $clienteContacto,
            "data" => $chatMessageEntity,
        ]);
        if ($toEmail) {
            return $this->emailService->send($subject, $message, $toEmail);
        } else {
            throw new Exception('Cliente contacto no tiene email');
        }
    }
}
