<?php
declare(strict_types=1);

/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link      https://cakephp.org CakePHP(tm) Project
 * @since     0.2.9
 * @license   https://opensource.org/licenses/mit-license.php MIT License
 */
namespace App\Controller;

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

/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @link https://book.cakephp.org/4/en/controllers.html#the-app-controller
 */
class AppController extends Controller
{
    /**
     * Initialization hook method.
     *
     * Use this method to add common initialization code like loading components.
     *
     * e.g. `$this->loadComponent('FormProtection');`
     *
     * @return void
     */
    public function initialize(): void
    {
        parent::initialize();

        $this->loadComponent('Flash');

        /*
         * Enable the following component for recommended CakePHP form protection settings.
         * see https://book.cakephp.org/4/en/controllers/components/form-protection.html
         */
        //$this->loadComponent('FormProtection');
    }

    public function beforeFilter(EventInterface $event): void
    {
        parent::beforeFilter($event);

        // Skip gating for the error handler
        if ((string)$this->request->getParam('controller') === 'Error') {
            return;
        }

        $sessionUser = $this->request->getSession()->read('Auth.User');

        $controller = (string)$this->request->getParam('controller');
        $action     = (string)$this->request->getParam('action');
        $pass       = (array)$this->request->getParam('pass');

        // ---------- PUBLIC ROUTES ----------
        $public = [
            'Users' => ['login','logout','forgotPassword','resetPassword','add','register'], // remove 'add' if no signup
            'Pages' => ['home','display'], // we'll special-case dashboard below
            'ContactSubmissions' => ['add'],
            // Cart/checkout are guest-friendly
            'Carts' => ['cart','index','addItem','removeItem','update','clear','checkout'],
            // Product browsing is public
            'Products' => ['listProducts','view'],
        ];

        $isPublic = isset($public[$controller]) && in_array($action, $public[$controller], true);

        // Protect Pages::display('dashboard')
        if ($controller === 'Pages' && $action === 'display' && (($pass[0] ?? null) === 'dashboard')) {
            $isPublic = false;
        }

        // ---------- REQUIRE LOGIN ----------
        if (!$sessionUser && !$isPublic) {
            $target = $this->request->getRequestTarget(); // original path + query
            $this->redirect([
                'controller' => 'Users',
                'action'     => 'login',
                '?'          => ['redirect' => $target],
            ]);
            $event->stopPropagation();
            $this->autoRender = false;
            return;
        }

        // ---------- ADMIN-ONLY ROUTES ----------
        $adminOnly = [
            'Pages' => ['display:dashboard'], // Pages::display('dashboard')
            'Users' => ['index','view','edit','delete'],   // keep 'add' public if you allow signup
            'Products' => ['add','edit','delete','index'],         // browsing is public
            'Allergens' => '*',
            'Orders' => '*',
            // Only the *CRUD* for carts/cart_items is admin — NOT the public cart actions above
            'Carts' => ['add','edit','delete','view','index'], // if your CRUD exists; safe to keep
            'CartItems' => '*',
            'ContactSubmissions' => ['index','view','edit','delete'], // 'add' stayed public above
        ];

        $adminRoute = false;
        if (isset($adminOnly[$controller])) {
            $spec = $adminOnly[$controller];
            if ($spec === '*') {
                $adminRoute = true;
            } else {
                if ($controller === 'Pages' && $action === 'display' && (($pass[0] ?? null) === 'dashboard')) {
                    $adminRoute = true;
                } else {
                    $adminRoute = in_array($action, $spec, true);
                }
            }
        }

        if ($adminRoute && (($sessionUser['role'] ?? '') !== 'admin')) {
            $this->Flash->error('Admins only.');
            $this->redirect(['controller' => 'Pages', 'action' => 'home']);
            $event->stopPropagation();
            $this->autoRender = false;
            return;
        }
    }
}
