<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\EventInterface;

class AppController extends Controller
{
    public function initialize(): void
    {
        parent::initialize();

        $this->loadComponent('Flash');
        $this->loadComponent('Authentication.Authentication');
        $this->loadComponent('Recaptcha');
    }
    
    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);
    
        $identity = $this->Authentication->getIdentity();
        if (!$identity) {
            return; // unauthenticated — handled by Authentication component
        }
    
        $user = $this->fetchTable('Users')->get($identity->id, contain: ['Roles']);
    
        if ($user->role !== $identity->get('role')
            || $user->alias !== $identity->get('alias')) {
            $this->Authentication->setIdentity($user);
        }
    
        $userRole   = $user->role ?? 'participant';
        $controller = $this->request->getParam('controller');
        $action     = $this->request->getParam('action');
    
        if (!$this->isAuthorized($userRole, $controller, $action)) {
            $this->Flash->error(__('You do not have permission to access this page.'));
            $event->setResult($this->redirect(['controller' => 'Discussions', 'action' => 'areas']));
            return;
        }
    }
    public function beforeRender(\Cake\Event\EventInterface $event): void
    {
        parent::beforeRender($event);

        $unreadTotal = 0;
        $canMessage = false;

        $identity = $this->Authentication->getIdentity();
        if ($identity) {
            $role = $identity->get('role') ?? 'participant';
            $canMessage = in_array($role, ['admin', 'moderator', 'contributor'], true);

            if ($canMessage) {
                $userId = $identity->getIdentifier();
                $participants = $this->fetchTable('ConversationParticipants');
                $messages = $this->fetchTable('Messages');

                $rows = $participants->find()
                    ->where(['user_id' => $userId])
                    ->all();

                foreach ($rows as $row) {
                    $query = $messages->find()
                        ->where([
                            'conversation_id' => $row->conversation_id,
                            'user_id !=' => $userId,
                        ]);

                    if ($row->last_read_at) {
                        $query->where(['created >' => $row->last_read_at]);
                    }

                    $unreadTotal += $query->count();
                }
            }
        }

        $this->set(compact('unreadTotal', 'canMessage'));
    }

    /**
     * Centralized permission check.
     *
     * Admin    → full access to everything
     * Moderator → manage topics, discussions, comments, documents + view dashboard
     * Participant → public pages, own profile, comments on accessible topics,
     *               + uploading evidence as part of their own role/promotion request
     */
    private function isAuthorized(string $role, string $controller, string $action): bool
    {
        // Admin has full access
        if ($role === 'admin') {
            return true;
        }

        // Actions restricted to admin ONLY
        $adminOnly = [
            'Users'    => ['index', 'add', 'edit', 'delete', 'pending', 'approve', 'reject',
                'roleRequests', 'approveRoleRequest', 'rejectRoleRequest',
                'approvePromotion', 'rejectPromotion', 'suspend', 'unsuspend',
                'suspensionRecommendations', 'approveSuspensionRecommendation', 'denySuspensionRecommendation'],
            'Roles'    => ['index', 'view', 'add', 'edit', 'delete'],
            'Statuses' => ['index', 'view', 'add', 'edit', 'delete'],
            // Admin::dashboard is still moderator+ (see $moderatorRequired below).
            // Only the favicon management actions are admin-only.
            'Admin'    => ['uploadFavicon', 'removeFavicon'],
            // Topic visibility migration rewrites all comments + (un)wraps the
            // AES key — too sensitive for moderators. Reading the migration
            // payload also exposes comment content + member public keys,
            // which must stay admin-only.
            'Topics'   => ['commentsForMigration', 'migrateToPublic', 'migrateToPrivate', 'purgeEncrypted'],
            // Contact enquiries contain visitors' personal details; admins only.
            'Contact'  => ['enquiries', 'viewEnquiry', 'resolveEnquiry'],
        ];

        if (isset($adminOnly[$controller]) && in_array($action, $adminOnly[$controller])) {
            return false;
        }

        // Actions that require moderator OR admin
        $moderatorRequired = [
            'Topics'      => ['index', 'view', 'add', 'edit', 'delete'],
            'Discussions' => ['index', 'view', 'add', 'edit', 'delete'],
            'Admin'       => ['dashboard'],
            'Documents'   => ['upload', 'newVersion', 'delete'],
            'Meetings' => ['add','edit', 'delete'],
            'Reports' => ['index', 'view', 'resolve'],
            'Podcasts' => ['add', 'edit', 'delete', 'togglePublish'],
            'Users' => ['recommendSuspension'],
        ];

        if (isset($moderatorRequired[$controller]) && in_array($action, $moderatorRequired[$controller])) {
            return $role === 'moderator';
        }

        // Everything else (public pages, own profile, comments,
        // Documents::download for any logged-in user, etc.) is allowed
        return true;

        $internalRoles = ['admin', 'moderator', 'contributor'];

        $internalOnly = [
            'Conversations' => ['index', 'view', 'start', 'createGroup', 'addMember', 'removeMember', 'recipients', 'summary', 'unreadCount'],
            'Messages' => ['add', 'poll'],
        ];

        if (isset($internalOnly[$controller]) && in_array($action, $internalOnly[$controller], true)) {
            return in_array($role, $internalRoles, true);
        }
    }
}
