<?php
declare(strict_types=1);
/**
 * Main includes file for core
 *
 * @author Andrew Morgan <andrew.morgan@mtcmedia.co.uk>
 */

use MTC\Core\Setting as Setting;
use Illuminate\Pagination\Paginator;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\ErrorHandler\ErrorHandler;

// Display all errors if local or staging.
if (file_exists(dirname(__FILE__) . '/../../.git')) {
    error_reporting(-1);
    ini_set('display_errors', 1);
}

// If we don't have path defined we will assume this is from root dir - e.g. phpunit
if (!isset($path)) {
    ini_set('display_errors', 1);
    $path = './';
}
define('START_TIME', microtime(true));

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

$currentSessionStatus = session_status();
if ($currentSessionStatus !== PHP_SESSION_ACTIVE) {
    session_start();
}
if (!ini_get('date.timezone')) {
    date_default_timezone_set('Europe/London');
}

//Detect the site in use
require_once SITE_PATH . '/sites/sites.php';
require_once SITE_PATH . '/sites/loader.php';

/* Composer Integration */
require_once SITE_PATH . '/vendor/autoload.php';

// Bring in settings from DB
//require_once $path . 'core/includes/settings.php';
$app = require_once $path . 'core/includes/container.php';

// register services
(new Illuminate\Events\EventServiceProvider($app))->register();

require_once $path . 'core/includes/eloquent.php';

Setting::import();
Setting::loadAndDefine();

// Security Headers
header('X-Frame-Options: SAMEORIGIN');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
if (Util::is_https()) {
    header('Strict-Transport-Security: max-age=31536000; includeSubdomains');
}

// unsetting the variable to prevent any $app variable collisions
// if you ever need to get the container instance,
// use Illuminate\Support\Facades\App::getInstance(),
// but most of the time App facade should be used.
// Using container via App facade:
// http://laravel.com/docs/4.2/ioc
unset($app);

// error_reporting(E_ALL);
error_reporting(E_ALL ^ E_NOTICE);

if (DEV_MODE && config('app.env') !== 'production') {
    // check if FirePHP extension is installed
    if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'FirePHP') !== false) {
        require_once SITE_PATH . "/core/includes/error_reporting_firephp.php";
    } else {
        if (php_sapi_name() != "cli") {
            //$whoops = new \Whoops\Run;
            //$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
            //$whoops->register();

            Debug::enable();
            ErrorHandler::register();
        }
    }
} else {
    ini_set('display_errors', 0);
}

/*
 * Bring in default arrays for locations
 */
require_once $path . 'core/includes/location_arrays/county_list.php';

require_once $path . 'core/includes/functions.php';

$loaded_module_paths = array();
$loaded_module_hooks = array();

require_once $path . 'core/includes/twig.php';
$isAjaxBootstrap = !empty($exclude_header_inc['not_for_ajax']);
if (!$isAjaxBootstrap) {
    require_once $path . 'core/includes/functions.twig.php';
    require_once $path . 'core/includes/timthumb.php';
}

// Set up default currency
require_once $path . 'core/includes/currency_detect.php';
/**
 * Register auto loader function located in functions.php
 */
spl_autoload_register('__mtc_autoload_classes');

foreach ($loaded_module_hooks as $module_hook) {
    require_once $module_hook;
}

require_once $path . 'core/admin/seoadmin/includes/settings.php';
// Image folders

$image_folders = [];

require_once $path . 'shop/includes/header.inc.php';

if (defined('CMS_ENABLED') && CMS_ENABLED && empty($exclude_header_inc['cms'])) {
    require_once $path . 'cms/includes/header.inc.php';
}

$appEnvironment = config('app.env');

if (!$isAjaxBootstrap) {
    if (!isset($seoadmin)) {
        $seoadmin = new Seo();
        $seoadmin->getSeoData();
    }

    //SEO redirect
    SeoRedirect::redirectToPage($seoadmin->path);

    $nofollow = !config('seo.indexing');

    /* Admin area authentication */
    // Cache getcwd() result for performance
    $currentWorkingDir = getcwd() ?: '';
    if (strpos($currentWorkingDir . '/', '/admin/')) {
        include $path . 'core/admin/includes/header.inc.php';
    }

    /* Load Plugins and Modules */
    if (count($loaded_module_paths) > 0) {
        foreach ($loaded_module_paths as $module) {
            include($module);
        }
    }

    /*
     * After Core, Shop and CMS have included their image.folders.php and
     * plugins, modules have loaded their loader.php (where they define their $image_folders)
     * we load the site specific $image_folders
     *
     * The site specific image.folders.php is now just like twig or controller files -
     * you don't change them directly in repos but you - copy down and change.
     */
    $site_image_folders_filepath = SITE_PATH . '/' . THEME_PATH . '/settings/image_folders.php';
    if (file_exists($site_image_folders_filepath)) {
        require_once $site_image_folders_filepath;
    }

    /*
     * This is declared again so plugins and modules can both
     * use and set image folders.
     */

    /* Get all user defined settings */
    $settings = get_defined_constants(true);
    $settings = $settings['user'];

    // Prepare Twig globals to batch add for better performance
    $twigGlobals = [
        'seo_tags' => $seoadmin->data,
        'image_folders' => $image_folders,
        'asset_loader' => !(empty($_SESSION[AssetLoader::SESSION_VAR]) || $_SESSION[AssetLoader::SESSION_VAR] != true),
    ];

    if (file_exists(SITE_PATH . THEME_URL . '/min/a.css')) {
        $twigGlobals['a_css'] = file_get_contents(SITE_PATH
            . THEME_URL
            . '/min/a.css');
    }

    if (empty($_SESSION['multiple_requests'])) {
        $twigGlobals['inline_styles'] = true;
        $_SESSION['multiple_requests'] = true;
    }


    $twig->addFunction(new \Twig\TwigFunction('vite', function($asset_filename) {

    if (config('site.vite_dev_server') === true) {

            // Get the dev server URL from an environment variable
            $dev_server_url = config('site.vite_dev_server_url') ?: 'http://localhost:5173';

            // Correctly append the base path and the full asset filename
            return "{$dev_server_url}/public/build/sites/default/" . $asset_filename;
        }

        // Production mode - use the manifest file
        static $manifest = null;
        static $manifestLoaded = false;
        $manifest_path = SITE_PATH . '/public/build/manifest.json';
        if (!$manifestLoaded) {
            if (!file_exists($manifest_path)) {
                throw new Exception("Asset manifest not found: {$manifest_path}");
            }
            $manifest = json_decode((string)file_get_contents($manifest_path), true, 512, JSON_THROW_ON_ERROR);
            $manifestLoaded = true;
        }
        $key = 'sites/default/' . $asset_filename;
        if (!isset($manifest[$key])) {
            throw new Exception("Asset not found in Vite manifest: {$key}");
        }
        return '/public/build/' . $manifest[$key]['file'];
    }));

    $twig->addFunction(new \Twig\TwigFunction('vite_css', function($asset_filename) {
        // In dev, Vue HMR injects CSS automatically; no link tags needed.
        if (config('site.vite_dev_server') === true) {
            return [];
        }

        static $manifest = null;
        static $manifestLoaded = false;
        $manifest_path = SITE_PATH . '/public/build/manifest.json';
        if (!$manifestLoaded) {
            if (!file_exists($manifest_path)) {
                throw new Exception("Asset manifest not found: {$manifest_path}");
            }
            $manifest = json_decode((string)file_get_contents($manifest_path), true, 512, JSON_THROW_ON_ERROR);
            $manifestLoaded = true;
        }

        $key = 'sites/default/' . $asset_filename;
        if (!isset($manifest[$key])) {
            throw new Exception("Asset not found in Vite manifest: {$key}");
        }

        $collected = [];

        $collectCss = function($entryKey) use ($manifest, &$collected, &$collectCss) {
            if (!isset($manifest[$entryKey])) return;
            $entry = $manifest[$entryKey];
            if (!empty($entry['css'])) {
                foreach ($entry['css'] as $css) {
                    $collected[] = '/public/build/' . $css;
                }
            }
            if (!empty($entry['imports'])) {
                foreach ($entry['imports'] as $importKey) {
                    $collectCss($importKey);
                }
            }
        };

        $collectCss($key);

        // Remove duplicates and reindex
        return array_values(array_unique($collected));
    }));

    // Add settings to globals array
    $twigGlobals['settings'] = $settings;

    /* Set Global Twig Variables - batch add for performance */
    foreach ($twigGlobals as $key => $value) {
        $twig->addGlobal($key, $value);
    }

    if ($appEnvironment !== 'production' || $nofollow === true) {
        $page_meta['robots'] = 'noindex, nofollow';
    } else {
        $page_meta['robots'] = 'index, follow';
    }


    // define $_REQUEST indices for legacy admin checks
    if (!isset($_REQUEST['edit'])) {
        $_REQUEST['edit'] = null;
    }

    if (!isset($_REQUEST['delete'])) {
        $_REQUEST['delete'] = null;
    }

    if (!isset($_REQUEST['action'])) {
        $_REQUEST['action'] = null;
    }

    if (!isset($_REQUEST['message'])) {
        $_REQUEST['message'] = null;
    }


    //Note: removing this will break twig variables used globally across the site
    // Only when not in admin area
    // $currentWorkingDir already cached above for performance
    if (!str_contains($currentWorkingDir . '/', '/admin/') && empty($exclude_header_inc['cross_platform_controller'])) {
        $cross_platform_controller_path = SITE_PATH . THEME_PATH . '/templates/controllers/cross.platform.controller.php';
        if (! file_exists($cross_platform_controller_path)) {
            $cross_platform_controller_path = SITE_PATH . DEFAULT_THEME_PATH . '/templates/controllers/cross.platform.controller.php';
        }
        require_once $cross_platform_controller_path;
    }

    Paginator::currentPageResolver(function () {
        return isset($_GET['page']) ? $_GET['page'] : 1;
    });

    $args = [
        'twig' => &$twig,
        'member' => &$member
    ];

    $GLOBALS['flash_messages'] = $_SESSION['flash_messages'] ?? null;
    unset($_SESSION['flash_messages']);

    HooksAdapter::do_action_ref_array('pre_render_of_page', [$args]);
}
