<?php

namespace Velis\Bpm\Workflow\Handler;

use Psr\SimpleCache\InvalidArgumentException;
use ReflectionException;
use User\User;
use Velis\App;
use Velis\App\MobileNotice as AppMobileNotice;
use Velis\Bpm\Ticket\Ticket;
use Velis\Bpm\Workflow\Handler;
use Velis\Bpm\Workflow\Subject;
use Velis\Exception;
use Velis\Lang;
use Velis\Notification\MobileQueue;

/**
 * Mobile notice workflow handler
 * @author Łukasz Ostafin <lukasz.ostafin@velis.pl>
 */
class MobileNotice extends Handler
{
    /**
     * Department recipients buffer
     * @var int[][]
     */
    private static array $departmentRecipients = [];

    /**
     * Handler execution method
     *
     * @param Subject $subject
     * @param mixed $additionalData
     * @return void
     * @throws InvalidArgumentException
     * @throws ReflectionException
     * @throws Exception
     */
    public function run($subject, $additionalData): void
    {
        $ticketId   = $subject->id();
        $msg        = '#' . $ticketId . ': ';
        $event      = $this->_workflow->getEvent();

        $maxTitleLen = 100;
        $title = $subject->title;
        $msg .= (strlen($title) > $maxTitleLen) ? substr($title, 0, $maxTitleLen) . '...' : $title;
        $msg .= ' ';

        $msg .= '(';
        if ($event->id() == Ticket::EVENT_CHANGED) {
            $msg .= Lang::get('TICKET_TICKETS_UPDATE');
        } else {
            $msg .= Lang::get('TICKET_CREATED_TICKET');
        }
        $msg .= ')';

        if (App::$config->fcm->pushNotification) {
            $notificationData = [
                'title' => App::$config->layout->title,
                'body' => $msg,
            ];
            $messageData = [
                'ticket_id' => (string) $ticketId,
                'msg' => $msg,
                'notification_foreground' => 'true',
            ];

            $recipients = $this->_getRecipients($subject);
            if (empty($recipients)) {
                return;
            }

            $recipients = array_diff($recipients, [App::$user->id()]);

            $notification = new AppMobileNotice(
                AppMobileNotice::TICKET_EDIT,
                $messageData,
                $notificationData,
                false
            );
            $notification->addUsers($recipients)
                ->send();

            if ($recipients) {
                $this->success($subject, ['notification' => $notificationData, 'data' => $messageData, 'recipients' => $recipients]);
            }
        }
    }

    /**
     * Returns notification user IDs
     *
     * @param Subject $subject
     * @return int[]
     * @throws ReflectionException
     */
    protected function _getRecipients($subject)
    {
        if ($subject['responsible_user_id']) {
            return [$subject['responsible_user_id']];
        } elseif ($subject['responsible_department_id']) {
            // notification for privileged responsible department members
            // in ticket's complex
            $departmentId = $subject['responsible_department_id'];

            if (!array_key_exists($departmentId, self::$departmentRecipients)) {
                self::$departmentRecipients[$departmentId] = array_keys(
                    User::listAll($this->_getDepartmentRecipientsParams($subject), null, ['user_id'])
                );
            }
            return self::$departmentRecipients[$departmentId];
        }
    }

    /**
     * Returns department recipients query params
     *
     * @param Subject $subject
     * @return array
     */
    protected function _getDepartmentRecipientsParams($subject)
    {
        return [
            'active'              => 1,
            'priv'                => ['Ticket', 'DepartmentNotification'],
            'department_id'       => $subject['responsible_department_id'],
        ];
    }
}
