<?php

namespace IMATHUZH\Qfq\Core\Form\FormElement;

use IMATHUZH\Messenger\AuthorizationToken;
use IMATHUZH\Messenger\TokenStorage;
use IMATHUZH\Qfq\Core\Form\Chat;
use IMATHUZH\Qfq\Core\Form\Form;
use IMATHUZH\Qfq\Core\Helper\Path;
use IMATHUZH\Qfq\Core\Helper\Support;

class ChatFormElement extends AbstractFormElement {
    public array $windowHtmlAttributes = array();
    public array $textAreaAttributes = array();
    public array $jsonChat = array();

    private $chatConfig;
    private string $chatConfigJson;
    private string $websocketUrl;
    private string $typeAheadUrl;

    /**
     * @param $attributes
     * @param Form|null $form
     * @throws \CodeException
     * @throws \DbException
     * @throws \DownloadException
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     * @throws \UserFormException
     * @throws \UserReportException
     */
    public function __construct($attributes, ?Form $form = null) {
        parent::__construct($attributes, $form);

        $this->sip = $this->store->getSipInstance();

        $this->chatConfig = Chat::createChatConfig($this->attributes);
        $dbColumnNames = $this->chatConfig[CHAT_DB_COLUMN_NAMES];
        $doneResetParam = '&resetDone=false';
        if ($this->chatConfig[CHAT_PARAMETER_OPTION_TAG_DONE_RESET]) {
            $doneResetParam = '&resetDone=true';
        }

        $this->chatConfigJson = json_encode($this->chatConfig, JSON_UNESCAPED_SLASHES);
        $this->websocketUrl = $this->store::getVar(SYSTEM_WEBSOCKET_URL, STORE_SYSTEM) ?? '';
        $this->typeAheadUrl = $this->store::getVar(SYSTEM_BASE_URL, STORE_SYSTEM) . 'typo3conf/ext/qfq/Classes/Api/typeahead.php';


        // Part 1: Build fieldset for chat
        $this->htmlAttributes['data-chat'] = 1;
        $this->htmlAttributes['data-load'] = $this->attributes[FE_DYNAMIC_UPDATE] === 'yes' ? 'data-load' : '';
        $this->htmlAttributes[ATTRIBUTE_DATA_REFERENCE] = $this->attributes[FE_DATA_REFERENCE];

        array_push($this->cssClasses, $this->attributes[F_FE_FIELDSET_CLASS], 'qfq-chat', 'qfq-skip-dirty');

        // Part 2: Build chat window content
        $this->windowHtmlAttributes[HTML_ATTR_NAME] = $this->htmlAttributes[HTML_ATTR_NAME] . '-chat';
        $this->windowHtmlAttributes[ATTRIBUTE_DATA_REFERENCE] = $this->attributes[FE_DATA_REFERENCE] . '-chat';

        $this->windowHtmlAttributes['data-chat-config'] = $this->chatConfigJson;
        $this->windowHtmlAttributes['data-websocket-url'] = $this->websocketUrl;

        // Mint a session-bound nchan-messages token so the Chat's JS can
        // open an authenticated WebSocket to the messenger endpoint. Chat
        // notifications are published server-side from saveChatMessage /
        // setDone / setTag, so the browser only needs listener permissions
        // on this chat's channel plus a personal 'user_<pIdCreator>' channel
        // for targeted notifications.
        $messengerGroup = $this->store::getVar(SYSTEM_MESSENGER_GROUP, STORE_SYSTEM) ?: MESSENGER_DEFAULT_GROUP;
        $messengerChannel = Chat::buildChannel($this->chatConfig);
        $messengerSub = [$messengerChannel];
        $pIdCreator = $this->chatConfig[CHAT_COLUMN_PID_CREATOR] ?? 0;
        if ($pIdCreator) {
            $messengerSub[] = 'user_' . $pIdCreator;
        }
        $messengerToken = '';
        try {
            $tokenObject = AuthorizationToken::createListenerToken(
                $messengerGroup,
                $messengerSub
            );
            $messengerToken = (new TokenStorage(
                $_SESSION[SESSION_NAME],
                unserialize($_SESSION[SESSION_NAME][SESSION_STORE_PREFIX . '-' . STORE_USER] ?? '') ?: [],
                unserialize($_SESSION[SESSION_NAME][SESSION_STORE_PREFIX . '-' . STORE_WEB] ?? '') ?: []
            ))->saveToken($tokenObject);
        } catch (\Throwable $e) {
            // No QFQ session available (e.g. CLI render, tests) — leave token
            // empty. JS will log a warning and nchan will reject the WS upgrade,
            // but history loading over the SIP-protected chat_load API keeps
            // working unchanged.
        }
        $this->windowHtmlAttributes['data-messenger-group'] = $messengerGroup;
        $this->windowHtmlAttributes['data-messenger-channel'] = $messengerChannel;
        $this->windowHtmlAttributes['data-messenger-token'] = $messengerToken;
        $this->windowHtmlAttributes['data-typeahead-url'] = $this->typeAheadUrl;
        $this->windowHtmlAttributes['data-load-api'] = $this->sip->queryStringToSip(Path::urlApi(API_LOAD_PHP) . '?' . 'mode=chat_load&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-save-api'] = $this->sip->queryStringToSip(Path::urlApi(API_SAVE_PHP) . '?' . 'mode=chat_save&chat_config=' . $this->chatConfigJson . $doneResetParam, RETURN_URL);
        $this->windowHtmlAttributes['data-attachment-api'] = $this->sip->queryStringToSip(Path::urlApi(API_SAVE_PHP) . '?' . 'mode=' . CHAT_MODE_ATTACHMENT_UPLOAD . '&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-toolbar-load-api'] = $this->sip->queryStringToSip(Path::urlApi(API_LOAD_PHP) . '?' . 'mode=chat_toolbar_load&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-reaction-add-api'] = $this->sip->queryStringToSip(Path::urlApi(API_SAVE_PHP) . '?' . 'mode=' . CHAT_MODE_REACTION_ADD . '&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-reaction-delete-api'] = $this->sip->queryStringToSip(Path::urlApi(API_SAVE_PHP) . '?' . 'mode=' . CHAT_MODE_REACTION_DELETE . '&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-video-call-start-api'] = $this->sip->queryStringToSip(Path::urlApi(API_SAVE_PHP) . '?' . 'mode=' . CHAT_MODE_VIDEO_CALL_START . '&chat_config=' . $this->chatConfigJson, RETURN_URL);
        $this->windowHtmlAttributes['data-jitsi-base-url'] = $this->store::getVar(SYSTEM_JITSI_BASE_URL, STORE_SYSTEM) ?? '';
        $this->windowHtmlAttributes['data-emoji-data-source'] = Path::urlExt('Resources/Public/JavaScript/emoji-data.json');

        $typeAheadParam = 'typeAheadSql=[1]SELECT ' . $dbColumnNames[CHAT_COLUMN_ID] . ',' . $dbColumnNames[CHAT_COLUMN_MESSAGE] . ' FROM ' . $this->chatConfig[CHAT_TABLE_NAME] . ' WHERE ' . $dbColumnNames[CHAT_COLUMN_TYPE] . ' = "' . CHAT_COLUMN_TYPE_TAG . '" AND ' . $dbColumnNames[CHAT_COLUMN_MESSAGE]
            . ' != "' . CHAT_TYPE_TAG_DONE . '" AND ' . $dbColumnNames[CHAT_COLUMN_MESSAGE] . ' LIKE ? GROUP BY ' . $dbColumnNames[CHAT_COLUMN_MESSAGE] . ' ORDER BY ' . $dbColumnNames[CHAT_COLUMN_MESSAGE] . ' LIMIT 10&typeAheadSqlPrefetch=';
        $this->windowHtmlAttributes['data-typeahead-sip'] = $this->sip->queryStringToSip($typeAheadParam, RETURN_SIP);
        $this->jsonChat = Chat::createChat($this->chatConfig, $this->databaseManager->getQfqDb(), '', 'refresh', $this->store);


        // Part 3: Prepare input field
        $colsRows = explode(',', $this->attributes[FE_SIZE], 3);
        if (empty($colsRows[1])) {
            $colsRows[1] = 1;
        }

        $this->textAreaAttributes[HTML_ATTR_ID] = $this->attributes[FE_HTML_ID] . '-chat-i';
        $this->textAreaAttributes[HTML_ATTR_CLASS] = 'form-control chat-input-field qfq-skip-dirty qfq-auto-grow';
        $this->textAreaAttributes[HTML_ATTR_NAME] = $this->attributes[HTML_ATTR_NAME] . '-input';
        $this->textAreaAttributes[ATTRIBUTE_DATA_REFERENCE] = $this->attributes[FE_DATA_REFERENCE] . '-input';
        $this->textAreaAttributes['cols'] = $colsRows[0];
        $this->textAreaAttributes['rows'] = $colsRows[1];

        // Check if $colsRows[2] != 0 >> enable auto-grow (if nothing is defined: enable auto-grow)
        $inputClass = 'form-control chat-input-field qfq-skip-dirty';
        $maxHeight = $colsRows[2] ?? '350';
        if ($maxHeight != '0') {
            $inputClass .= ' ' . CLASS_FORM_ELEMENT_AUTO_GROW;
            $this->textAreaAttributes[ATTRIBUTE_DATA_MAX_HEIGHT] = $maxHeight;
        }

        if ($this->attributes[FE_MAX_LENGTH] > 0) {
            $this->textAreaAttributes['maxlength'] = $this->attributes[FE_MAX_LENGTH];
        }
        if ($this->attributes[FE_MODE] == FE_MODE_REQUIRED) {
            $this->textAreaAttributes[F_FE_DATA_REQUIRED_ERROR] = $this->attributes[F_FE_DATA_REQUIRED_ERROR];
        }
    }
}










