<?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     3.3.0
 * @license   https://opensource.org/licenses/mit-license.php MIT License
 */

namespace App;

use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Authenticator\AuthenticatorInterface;
use Cake\Core\Configure;
use Cake\Core\ContainerInterface;
use Cake\Datasource\FactoryLocator;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\BaseApplication;
use Cake\Http\Middleware\BodyParserMiddleware;
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\Http\ServerRequest;
use Cake\ORM\Locator\TableLocator;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Cake\Http\Response;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Cake\Routing\Route\Route;
use Cake\Routing\Router;
use App\Middleware\PermisosMiddleware;

/**
 * Application setup class.
 *
 * This defines the bootstrapping logic and middleware layers you
 * want to use in your application.
 *
 * @extends \Cake\Http\BaseApplication<\App\Application>
 */
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    /**
     * Load all the application configuration and bootstrap logic.
     *
     * @return void
     */
    public function bootstrap(): void
    {
        // Call parent to load bootstrap from files.
        parent::bootstrap();

        if (PHP_SAPI !== 'cli') {
            FactoryLocator::add(
                'Table',
                (new TableLocator())->allowFallbackClass(false)
            );
        }
    }

    /**
     * Setup the middleware queue your application will use.
     *
     * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
     * @return \Cake\Http\MiddlewareQueue The updated middleware queue.
     */
   public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $middlewareQueue
        ->add(new ErrorHandlerMiddleware(Configure::read('Error'), $this))
        ->add(new AssetMiddleware([
            'cacheTime' => Configure::read('Asset.cacheTime'),
        ]))
        ->add(new RoutingMiddleware($this))
        ->add(new BodyParserMiddleware())
        ->add(new AuthenticationMiddleware($this));

    return $middlewareQueue;
}

    /**
     * Register application container services.
     *
     * @param \Cake\Core\ContainerInterface $container The Container to update.
     * @return void
     * @link https://book.cakephp.org/5/en/development/dependency-injection.html#dependency-injection
     */
    public function services(ContainerInterface $container): void {}
    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $params = $request->getAttribute('params');
        $isPortal = isset($params['prefix']) && $params['prefix'] === 'Portal';

        if ($isPortal) {
            return $this->getPortalAuthenticationService();
        }

        $authenticationService = new AuthenticationService([
            'unauthenticatedRedirect' => Router::url([
                'controller' => 'Users',
                'action' => 'login',
            ]),
            'queryParam' => 'redirect',
        ]);

        $authenticationService->loadIdentifier('Authentication.Password', [
            'fields' => [
                'username' => 'username',
                'password' => 'password',
            ]
        ]);

        $authenticationService->loadAuthenticator('Authentication.Session');

        $authenticationService->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'username',
                'password' => 'password',
            ],
            'loginUrl' => Router::url([
                'controller' => 'Users',
                'action' => 'login',
            ]),
        ]);

        return $authenticationService;
    }

    /**
     * Servicio de autenticación independiente para el portal de clientes.
     * Usa su propia tabla de credenciales (ClientesCredenciales), separada
     * por completo del sistema de permisos de staff (Users/Permisos).
     */
    protected function getPortalAuthenticationService(): AuthenticationServiceInterface
    {
        $authenticationService = new AuthenticationService([
            'unauthenticatedRedirect' => Router::url([
                'prefix' => 'Portal',
                'controller' => 'Portal',
                'action' => 'login',
            ]),
            'queryParam' => 'redirect',
        ]);

        $authenticationService->loadIdentifier('Authentication.Password', [
            'resolver' => [
                'className' => 'Authentication.Orm',
                'userModel' => 'ClientesCredenciales',
                'finder' => 'auth',
            ],
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
        ]);

        $authenticationService->loadAuthenticator('Authentication.Session', [
            'sessionKey' => 'PortalAuth',
        ]);

        $authenticationService->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
            'loginUrl' => Router::url([
                'prefix' => 'Portal',
                'controller' => 'Portal',
                'action' => 'login',
            ]),
        ]);

        return $authenticationService;
    }

    public function process(ServerRequest $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $user = $request->getAttribute('identity');

        // Rutas protegidas
        $protectedRoutes = [
            'usuarios/index' => [1],
            'usuarios/delete' => [1],
            'usuarios/edit' => [1],
            'pacientes/add/' => [1, 2],
            'pacientes/edit/' => [1, 2],
        ];

        $path = $request->getUri()->getPath();
        foreach ($protectedRoutes as $route => $allowedRoles) {
            if (preg_match('#^' . $route . '(/.*)?$#', $path)) {
                if (!$user || !in_array($user['rol'], $allowedRoles)) {
                    return new Response(['body' => 'No tienes permiso para acceder a esta página', 'status' => 403]);
                }
            }
        }

        return $handler->handle($request);
    }
}
