<?php
/**
 * DroidTester Publisher Panel — Bootstrap
 *
 * Loaded at the top of every request. Sets up:
 *  - Error reporting (based on APP_DEBUG)
 *  - Timezone
 *  - .env loader → constants
 *  - Autoloader for /payment/ and /includes/
 *  - Global exception/error handler
 */

declare(strict_types=1);

// ────────────────────────────────────────────────────────────
// 1. Project root constants (idempotent)
// ────────────────────────────────────────────────────────────
defined('ROOT_PATH')     or define('ROOT_PATH', dirname(__DIR__));
defined('CONFIG_PATH')   or define('CONFIG_PATH', ROOT_PATH . '/config');
defined('INCLUDES_PATH') or define('INCLUDES_PATH', ROOT_PATH . '/includes');
defined('PAYMENT_PATH')  or define('PAYMENT_PATH', ROOT_PATH . '/payment');
defined('UPLOADS_PATH')  or define('UPLOADS_PATH', ROOT_PATH . '/uploads');
defined('LOGS_PATH')     or define('LOGS_PATH', ROOT_PATH . '/logs');

// ────────────────────────────────────────────────────────────
// 2. Load .env into $_ENV + getenv()
// ────────────────────────────────────────────────────────────
function loadEnv(string $path): void
{
    if (!is_readable($path)) {
        die('Critical: .env file missing or unreadable at ' . $path);
    }
    $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        if (str_starts_with(trim($line), '#')) continue;
        if (!str_contains($line, '=')) continue;

        [$key, $value] = explode('=', $line, 2);
        $key = trim($key);
        $value = trim($value);

        // Strip surrounding quotes
        if (strlen($value) >= 2 && (
            (str_starts_with($value, '"') && str_ends_with($value, '"')) ||
            (str_starts_with($value, "'") && str_ends_with($value, "'"))
        )) {
            $value = substr($value, 1, -1);
        } else {
            // For unquoted values, strip inline `# comment`
            // (only if # is preceded by whitespace, so we don't break '#1B7A43' colors)
            if (preg_match('/^(.*?)\s+#.*$/', $value, $m)) {
                $value = trim($m[1]);
            }
        }

        $_ENV[$key] = $value;
        putenv("$key=$value");
    }
}

loadEnv(ROOT_PATH . '/.env');

// ────────────────────────────────────────────────────────────
// 3. Helper to read env with default
// ────────────────────────────────────────────────────────────
function env(string $key, mixed $default = null): mixed
{
    $value = $_ENV[$key] ?? getenv($key);
    if ($value === false || $value === null) return $default;

    // Cast common types
    $lower = strtolower((string)$value);
    return match ($lower) {
        'true', '(true)'   => true,
        'false', '(false)' => false,
        'null', '(null)'   => null,
        'empty', '(empty)' => '',
        default            => $value,
    };
}

// ────────────────────────────────────────────────────────────
// 4. Define key constants from env
// ────────────────────────────────────────────────────────────
define('APP_NAME', env('APP_NAME', 'DroidTester'));
define('APP_URL', rtrim((string)env('APP_URL', ''), '/'));
define('APP_ENV', env('APP_ENV', 'production'));
define('APP_DEBUG', (int)env('APP_DEBUG', 0) === 1);

// ────────────────────────────────────────────────────────────
// 5. Timezone
// ────────────────────────────────────────────────────────────
date_default_timezone_set((string)env('TIMEZONE', 'Asia/Kolkata'));

// ────────────────────────────────────────────────────────────
// 6. Error reporting
// ────────────────────────────────────────────────────────────
if (APP_DEBUG) {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
} else {
    error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
    ini_set('display_errors', '0');
}
ini_set('log_errors', '1');
ini_set('error_log', LOGS_PATH . '/php-error.log');

// ────────────────────────────────────────────────────────────
// 7. Simple autoloader for payment/ classes
// ────────────────────────────────────────────────────────────
spl_autoload_register(function (string $class): void {
    $candidates = [
        PAYMENT_PATH . '/' . $class . '.php',
        PAYMENT_PATH . '/gateways/' . $class . '.php',
        PAYMENT_PATH . '/helpers/' . $class . '.php',
    ];
    foreach ($candidates as $file) {
        if (file_exists($file)) {
            require_once $file;
            return;
        }
    }
});

// ────────────────────────────────────────────────────────────
// 8. Load core helpers (order matters)
// ────────────────────────────────────────────────────────────
require_once INCLUDES_PATH . '/response.php';
require_once INCLUDES_PATH . '/logger.php';
require_once INCLUDES_PATH . '/db.php';
require_once INCLUDES_PATH . '/redis.php';
require_once INCLUDES_PATH . '/session.php';
require_once INCLUDES_PATH . '/csrf.php';
require_once INCLUDES_PATH . '/rate-limit.php';
require_once INCLUDES_PATH . '/validator.php';
require_once INCLUDES_PATH . '/mail.php';
require_once INCLUDES_PATH . '/auth-guard.php';

// ────────────────────────────────────────────────────────────
// 9. Global exception handler
// ────────────────────────────────────────────────────────────
set_exception_handler(function (Throwable $e): void {
    Logger::error('Uncaught exception', [
        'message' => $e->getMessage(),
        'file'    => $e->getFile(),
        'line'    => $e->getLine(),
        'trace'   => APP_DEBUG ? $e->getTraceAsString() : null,
    ]);

    if (PHP_SAPI === 'cli') {
        echo "Error: " . $e->getMessage() . "\n";
        exit(1);
    }

    http_response_code(500);
    if (str_contains((string)($_SERVER['REQUEST_URI'] ?? ''), '/api/')) {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode([
            'status'  => 'error',
            'message' => APP_DEBUG ? $e->getMessage() : 'Internal server error',
        ]);
    } else {
        $errFile = ROOT_PATH . '/error/500.html';
        if (file_exists($errFile)) readfile($errFile);
        else echo '<h1>500 — Internal Server Error</h1>';
    }
    exit;
});

// ────────────────────────────────────────────────────────────
// 10. Maintenance mode check
// ────────────────────────────────────────────────────────────
if ((int)env('MAINTENANCE_MODE', 0) === 1
    && !str_contains((string)($_SERVER['REQUEST_URI'] ?? ''), '/api/payment/webhook')) {
    http_response_code(503);
    header('Retry-After: 600');
    if (str_contains((string)($_SERVER['REQUEST_URI'] ?? ''), '/api/')) {
        header('Content-Type: application/json');
        echo json_encode(['status' => 'maintenance', 'message' => env('MAINTENANCE_MESSAGE')]);
    } else {
        echo '<h1>' . htmlspecialchars((string)env('MAINTENANCE_MESSAGE'), ENT_QUOTES) . '</h1>';
    }
    exit;
}
