<?php
declare(strict_types=1);

/**
 * ACC Standalone Bootstrap (Final / Clean)
 * - Auto-loads controllers from /includes/controllers
 * - Registers REST routes for any controller class that has register_routes()
 * - Provides debug via ?debug_routes=1
 */

if (!defined('ACC_BASE_PATH')) {
    define('ACC_BASE_PATH', dirname(__DIR__));
}

/**
 * ------------------------------------------------------------
 * Load config
 * ------------------------------------------------------------
 */
require_once ACC_BASE_PATH . '/standalone/config.php';

// Security headers / CORS / runtime hardening (API entry)
if (function_exists('acc_security_boot')) {
    acc_security_boot(true);
}

/**
 * ------------------------------------------------------------
 * Error handling
 * ------------------------------------------------------------
 */
if (defined('ACC_DEBUG') && ACC_DEBUG) {
    ini_set('display_errors', '1');
    ini_set('display_startup_errors', '1');
    error_reporting(E_ALL);
} else {
    ini_set('display_errors', '0');
    ini_set('display_startup_errors', '0');
    // keep fatal errors, hide noisy stuff
    error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED);
}

/**
 * ------------------------------------------------------------
 * WordPress-like constants
 * ------------------------------------------------------------
 */
if (!defined('ABSPATH')) define('ABSPATH', ACC_BASE_PATH . DIRECTORY_SEPARATOR);
if (!defined('ACC_PATH')) define('ACC_PATH', ACC_BASE_PATH . DIRECTORY_SEPARATOR);
if (!defined('ACC_URL')) define('ACC_URL', '/acc-engine/');
if (!defined('ARRAY_A')) define('ARRAY_A', 'ARRAY_A');
if (!defined('ARRAY_N')) define('ARRAY_N', 'ARRAY_N');
if (!defined('OBJECT')) define('OBJECT', 'OBJECT');

/**
 * ------------------------------------------------------------
 * Minimal WordPress stubs (only if missing)
 * ------------------------------------------------------------
 */
if (!function_exists('add_action')) {
    function add_action(...$args): bool { return true; }
}
if (!function_exists('add_filter')) {
    function add_filter(...$args): bool { return true; }
}
if (!function_exists('do_action')) {
    function do_action(...$args): bool { return true; }
}
if (!function_exists('apply_filters')) {
    function apply_filters($tag, $value = null, ...$args) { return $value; }
}
if (!function_exists('__')) {
    function __($text, $domain = null) { return $text; }
}
if (!function_exists('_e')) {
    function _e($text, $domain = null): void { echo $text; }
}
if (!function_exists('esc_html')) {
    function esc_html($text): string {
        return htmlspecialchars((string)$text, ENT_QUOTES, 'UTF-8');
    }
}
if (!function_exists('esc_attr')) {
    function esc_attr($text): string {
        return htmlspecialchars((string)$text, ENT_QUOTES, 'UTF-8');
    }
}
if (!function_exists('esc_url')) {
    function esc_url($url): string {
        return (string) filter_var((string) $url, FILTER_SANITIZE_URL);
    }
}
if (!function_exists('wp_die')) {
    function wp_die($message = '', $title = '', $args = []): void {
        acc_json_response([
            'success' => false,
            'error'   => 'wp_die',
            'message' => (string) $message,
        ], 500);
    }
}

/**
 * ------------------------------------------------------------
 * Load compatibility layer + router dependencies
 * ------------------------------------------------------------
 */
require_once ACC_BASE_PATH . '/standalone/wp_compat.php';

/**
 * Ensure globals exist
 */
if (!isset($GLOBALS['wp_rest_routes']) || !is_array($GLOBALS['wp_rest_routes'])) $GLOBALS['wp_rest_routes'] = [];
if (!isset($GLOBALS['acc_rest_routes']) || !is_array($GLOBALS['acc_rest_routes'])) $GLOBALS['acc_rest_routes'] = [];

/**
 * ------------------------------------------------------------
 * Database connection
 * ------------------------------------------------------------
 */
try {
    $pdo = new PDO(
        ACC_DB_DSN,
        ACC_DB_USER,
        ACC_DB_PASS,
        [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES   => false,
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . ACC_DB_CHARSET,
        ]
    );
} catch (Throwable $e) {
    acc_json_response([
        'success' => false,
        'error'   => 'database_connection_failed',
        'message' => (defined('ACC_DEBUG') && ACC_DEBUG) ? $e->getMessage() : 'Database connection failed',
    ], 500);
}

/**
 * wpdb adapter
 */
require_once ACC_BASE_PATH . '/standalone/wpdb_adapter.php';
$GLOBALS['wpdb'] = new ACC_WPDB_Adapter($pdo, ACC_DB_PREFIX);

/**
 * ACL compat + router
 */
require_once ACC_BASE_PATH . '/includes/helpers/acl-scope-registry.php';
require_once ACC_BASE_PATH . '/includes/helpers/acl-scope-enforce.php';
require_once ACC_BASE_PATH . '/includes/helpers/acl-functions.php';
require_once ACC_BASE_PATH . '/standalone/acl_compat.php';
require_once ACC_BASE_PATH . '/standalone/router.php';
require_once ACC_BASE_PATH . '/standalone/controller_loader.php';

/**
 * ------------------------------------------------------------
 * Controller loading (lazy by request path)
 * ------------------------------------------------------------
 */
$controllersBasePath    = ACC_BASE_PATH . '/includes/controllers';
$requestPathEarly         = acc_request_path_early();
$controllerLoad           = acc_load_controllers_for_path($requestPathEarly);
$loadedControllerFiles    = $controllerLoad['loaded'];
$controllerLoadErrors     = $controllerLoad['errors'];
$controllerClasses        = $controllerLoad['classes'];
$missingControllerFiles   = [];

/**
 * ------------------------------------------------------------
 * Register routes + compile dispatch index
 * ------------------------------------------------------------
 */
$controllerRegisterErrors = acc_register_controller_routes($controllerClasses);
acc_route_compile_index();

/**
 * ------------------------------------------------------------
 * Debug: list routes
 * Usage: /acc-engine/api.php?debug_routes=1
 * ------------------------------------------------------------
 */
if (isset($_GET['debug_routes']) && (string)($_GET['debug_routes']) === '1') {
    $registeredRoutes = [];

    if (isset($GLOBALS['wp_rest_server']) && is_object($GLOBALS['wp_rest_server']) && method_exists($GLOBALS['wp_rest_server'], 'get_routes')) {
        $registeredRoutes = $GLOBALS['wp_rest_server']->get_routes();
    } elseif (isset($GLOBALS['wp_rest_routes']) && is_array($GLOBALS['wp_rest_routes'])) {
        $registeredRoutes = $GLOBALS['wp_rest_routes'];
    }

    acc_json_response([
        'success' => true,
        'debug'   => [
            'base_path'                      => ACC_BASE_PATH,
            'controllers_base_path'          => $controllersBasePath,

            'register_rest_route_exists'     => function_exists('register_rest_route'),
            'wp_rest_routes_global_exists'   => isset($GLOBALS['wp_rest_routes']),
            'wp_rest_routes_global_is_array' => isset($GLOBALS['wp_rest_routes']) && is_array($GLOBALS['wp_rest_routes']),
            'wp_rest_routes_global_count'    => (isset($GLOBALS['wp_rest_routes']) && is_array($GLOBALS['wp_rest_routes']))
                ? count($GLOBALS['wp_rest_routes'])
                : null,

            'loaded_controller_files_count'  => count($loadedControllerFiles),
            'loaded_controller_files'        => $loadedControllerFiles,
            'request_path_early'             => $requestPathEarly,
            'lazy_controllers'               => !acc_should_load_all_controllers(),
            'missing_controller_files'       => $missingControllerFiles,
            'controller_load_errors'         => $controllerLoadErrors,

            'registered_controller_classes'  => $controllerClasses,
            'controller_register_errors'     => $controllerRegisterErrors,

            'registered_routes_count'        => is_array($registeredRoutes) ? count($registeredRoutes) : 0,
            'registered_routes'              => is_array($registeredRoutes) ? array_keys($registeredRoutes) : [],
        ],
    ], 200);
}

/**
 * ------------------------------------------------------------
 * Helper: register controller routes
 * ------------------------------------------------------------
 */
function acc_register_controller_routes(array $classes): array
{
    $errors = [];

    foreach ($classes as $className) {
        if (!class_exists($className)) {
            continue;
        }
        if (!method_exists($className, 'register_routes')) {
            continue;
        }

        try {
            if (is_string($className) && method_exists($className, 'register_routes')) {
                $className::register_routes();
            }
        } catch (Throwable $e) {
            $errors[] = [
                'class'   => $className,
                'message' => $e->getMessage(),
            ];
        }
    }

    return $errors;
}
