<?php

namespace App\Twig;

use App\Entity\Comment;
use App\Entity\Group;
use App\Entity\LoginMessage;
use App\Entity\Member;
use App\Entity\Message;
use App\Repository\CommentRepository;
use App\Repository\LoginMessageRepository;
use App\Repository\MessageRepository;
use App\Utilities\ManagerTrait;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Routing\RouterInterface;
use Twig\Extension\AbstractExtension;
use Twig\Extension\GlobalsInterface;

class MemberTwigExtension extends AbstractExtension implements GlobalsInterface
{
    use ManagerTrait;

    private const ALL_TEAMS = [
        'communitynews' => [
            'trans' => 'AdminCommunityNews',
            'rights' => [Member::ROLE_ADMIN_COMMUNITYNEWS],
            'route' => 'admin_communitynews_overview',
        ],
        'words' => [
            'trans' => 'AdminWord',
            'rights' => [Member::ROLE_ADMIN_WORDS],
            'route' => 'translations',
        ],
        'flags' => [
            'trans' => 'AdminFlags',
            'rights' => [Member::ROLE_ADMIN_FLAGS],
            'route' => 'admin_flags',
        ],
        'rights' => [
            'trans' => 'AdminRights',
            'rights' => [Member::ROLE_ADMIN_RIGHTS],
            'route' => 'admin_rights_members',
        ],
        'logs' => [
            'trans' => 'AdminLogs',
            'rights' => [Member::ROLE_ADMIN_LOGS],
            'route' => 'admin_logs_overview',
        ],
        'comments' => [
            'trans' => 'AdminComments',
            'rights' => [Member::ROLE_ADMIN_SAFETYTEAM, Member::ROLE_ADMIN_COMMENTS],
            'route' => 'admin_comment_overview',
        ],
        'checker' => [
            'trans' => 'AdminChecker',
            'rights' => [Member::ROLE_ADMIN_SAFETYTEAM, Member::ROLE_ADMIN_CHECKER],
            'route' => 'admin_spam_activities',
        ],
        'newmembersbewelcome' => [
            'trans' => 'AdminNewMembers',
            'rights' => [Member::ROLE_ADMIN_SAFETYTEAM, Member::ROLE_ADMIN_NEWMEMBERSBEWELCOME],
            'route' => 'newmembers',
        ],
        'massmail' => [
            'trans' => 'AdminMassMail',
            'rights' => [Member::ROLE_ADMIN_MASSMAIL],
            'route' => 'admin_massmail',
        ],
        'treasurer' => [
            'trans' => 'AdminTreasurer',
            'rights' => [Member::ROLE_ADMIN_TREASURER],
            'route' => 'admin_treasurer_overview',
        ],
        'faq' => [
            'trans' => 'AdminFAQ',
            'rights' => [Member::ROLE_ADMIN_FAQ],
            'route' => 'admin_faqs_overview',
        ],
        'group' => [
            'trans' => 'AdminGroup',
            'rights' => [Member::ROLE_ADMIN_GROUP],
            'route' => 'admin_groups_approval',
            'minimum_level' => 10,
        ],
        'tools' => [
            'trans' => 'AdminVolunteerTools',
            'rights' => [
                Member::ROLE_ADMIN_SAFETYTEAM, Member::ROLE_ADMIN_ADMIN,
                Member::ROLE_ADMIN_SQLFORVOLUNTEERS, Member::ROLE_ADMIN_PROFILE,
                Member::ROLE_ADMIN_CHECKER, Member::ROLE_ADMIN_ACCEPTER,
            ],
            'route' => 'admin_volunteer_tools',
        ],
        'polls' => [
            'trans' => 'AdminPolls',
            'rights' => [Member::ROLE_ADMIN_POLL],
            'route' => 'polls',
        ],
    ];

    protected RouterInterface $router;

    protected Security $security;

    protected ?Member $member;

    public function __construct(
        RouterInterface $router,
        Security $security,
    ) {
        $this->router = $router;
        $this->security = $security;
        $this->member = $this->security->getUser();
    }

    public function getGlobals(): array
    {
        if (null === $this->member) {
            return [];
        }

        $teams = $this->getTeams();

        return [
            'loginmessages' => $this->getLoginMessages(),
            'groupsInApprovalQueue' => $this->getGroupsInApprovalQueueCount(),
            'reportedCommentsCount' => $this->getReportedCommentsCount(),
            'reportedMessagesCount' => $this->getReportedMessagesCount(),
            'conversationCount' => $this->getUnreadConversationsCount(),
            'teams' => $teams,
        ];
    }

    public function getName()
    {
        return self::class;
    }

    /**
     * @return array
     */
    protected function getTeams()
    {
        $roles = $this->security->getUser()->getRoles();

        $teams = [];
        $assignedTeams = [];
        foreach (self::ALL_TEAMS as $name => $team) {
            foreach ($roles as $role) {
                if (!\in_array($name, $assignedTeams, true)) {
                    if (\in_array($role, $team['rights'], true)) {
                        $add = true;
                        if (isset($team['minimum_level'])) {
                            $level = $this->member->getLevelForRight($role);
                            if ($level !== $team['minimum_level']) {
                                $add = false;
                            }
                        }
                        if ($add) {
                            $assignedTeams[] = $name;
                            $teams[] = [
                                'trans' => strtolower($team['trans']),
                                'route' => $team['route'],
                            ];
                        }
                    }
                }
            }
        }

        return $teams;
    }

    protected function getGroupsInApprovalQueueCount(): ?int
    {
        $groupsInApprovalCount = null;
        if ($this->security->isGranted(Member::ROLE_ADMIN_GROUP)) {
            $level = $this->member->getLevelForRight(Member::ROLE_ADMIN_GROUP);
            if (10 === $level) {
                $groupsRepository = $this->getManager()->getRepository(Group::class);
                $groups = $groupsRepository->findBy([
                    'approved' => Group::OPEN,
                ]);
                $groupsInApprovalCount = \count($groups);
            }
        }

        return $groupsInApprovalCount;
    }

    protected function getReportedCommentsCount(): ?int
    {
        $reportedCommentsCount = null;
        if (
            $this->security->isGranted(Member::ROLE_ADMIN_COMMENTS)
            || $this->security->isGranted(Member::ROLE_ADMIN_SAFETYTEAM)
        ) {
            /** @var CommentRepository $commentRepository */
            $commentRepository = $this->getManager()->getRepository(Comment::class);
            $reportedCommentsCount = $commentRepository->getReportedCommentsCount();
        }

        return $reportedCommentsCount;
    }

    protected function getReportedMessagesCount(): ?int
    {
        $reportedMessagesCount = null;
        if (
            $this->security->isGranted(Member::ROLE_ADMIN_CHECKER)
            || $this->security->isGranted(Member::ROLE_ADMIN_SAFETYTEAM)
        ) {
            /** @var MessageRepository $messageRepository */
            $messageRepository = $this->getManager()->getRepository(Message::class);

            $reportedMessagesCount = $messageRepository->getReportedMessagesCount();
        }

        return $reportedMessagesCount;
    }

    protected function getUnreadConversationsCount(): int
    {
        /** @var MessageRepository $messageRepository */
        $messageRepository = $this->getManager()->getRepository(Message::class);

        return $messageRepository->getUnreadConversationsCount($this->member);
    }

    protected function getLoginMessages(): array
    {
        /** @var LoginMessageRepository $loginMessagsRepository */
        $loginMessageRepository = $this->getManager()->getRepository(LoginMessage::class);

        return $loginMessageRepository->getLoginMessages($this->member);
    }
}
