<?php
namespace Core\System;

class Response
{
    public static function redirect($url, string $fallback = '/')
    {
        $target = self::sanitizeRedirectTarget((string) $url, $fallback);
        header('Location: ' . $target, true, 302);
        exit;
    }

    /**
     * Permanent redirect (301) — use for canonical URL consolidation so
     * search engines transfer full link equity to the canonical target.
     */
    public static function permanentRedirect($url, string $fallback = '/')
    {
        $target = self::sanitizeRedirectTarget((string) $url, $fallback);
        header('Location: ' . $target, true, 301);
        exit;
    }

    public static function back(string $fallback = '/')
    {
        $referer = (string)($_SERVER['HTTP_REFERER'] ?? '');
        self::redirect($referer, $fallback);
    }

    public static function sanitizeRedirectTarget(string $url, string $fallback = '/'): string
    {
        $fallback = self::normalizeInternalPath($fallback);
        $url = trim($url);

        if ($url === '') {
            return $fallback;
        }

        if (preg_match('/[
]/', $url)) {
            return $fallback;
        }

        $parts = @parse_url($url);
        if ($parts === false) {
            return $fallback;
        }

        if (!empty($parts['scheme']) || !empty($parts['host'])) {
            $currentHost = strtolower((string)($_SERVER['HTTP_HOST'] ?? ''));
            $targetHost = strtolower((string)($parts['host'] ?? ''));
            if ($currentHost === '' || $targetHost === '' || $currentHost !== $targetHost) {
                return $fallback;
            }
        }

        $path = (string)($parts['path'] ?? '');
        if ($path === '') {
            $path = '/';
        }

        if (!str_starts_with($path, '/')) {
            $path = '/' . ltrim($path, '/');
        }

        if (str_contains($path, '..')) {
            return $fallback;
        }

        $query = isset($parts['query']) && $parts['query'] !== '' ? '?' . $parts['query'] : '';
        $fragment = isset($parts['fragment']) && $parts['fragment'] !== '' ? '#' . preg_replace('/[^a-zA-Z0-9_\-]/', '', $parts['fragment']) : '';

        return $path . $query . $fragment;
    }

    private static function normalizeInternalPath(string $path): string
    {
        $path = trim($path);
        if ($path === '') {
            return '/';
        }

        if (!str_starts_with($path, '/')) {
            $path = '/' . ltrim($path, '/');
        }

        return preg_replace('#/+#', '/', $path) ?: '/';
    }
}
