<?php
namespace App\Core;

/** Pembantu respons HTTP. */
class Response
{
    public static function redirect(string $url, int $code = 302): void
    {
        if (!preg_match('#^https?://#i', $url)) {
            $url = Url::to($url);
        }
        header('Location: ' . $url, true, $code);
        exit;
    }

    public static function back(string $fallback = '/'): void
    {
        $ref = $_SERVER['HTTP_REFERER'] ?? '';
        $host = $_SERVER['HTTP_HOST'] ?? '';
        if ($ref && $host && str_contains($ref, $host)) self::redirect($ref);
        self::redirect($fallback);
    }

    public static function json($data, int $code = 200): void
    {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        header('X-Content-Type-Options: nosniff');
        echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        exit;
    }

    public static function abort(int $code, string $message = ''): void
    {
        http_response_code($code);
        $titles = [
            400 => 'Permintaan Tidak Valid',
            401 => 'Belum Masuk',
            403 => 'Akses Ditolak',
            404 => 'Halaman Tidak Ditemukan',
            405 => 'Metode Tidak Diizinkan',
            419 => 'Sesi Kedaluwarsa',
            422 => 'Data Tidak Valid',
            429 => 'Terlalu Banyak Permintaan',
            500 => 'Terjadi Kesalahan Sistem',
        ];
        $title = $titles[$code] ?? 'Terjadi Kesalahan';
        if (Request::isAjax()) {
            self::json(['sukses' => false, 'kode' => $code, 'judul' => $title, 'pesan' => $message], $code);
        }
        $view = dirname(__DIR__) . '/Views/errors/generic.php';
        if (is_file($view)) {
            extract(['code' => $code, 'title' => $title, 'message' => $message]);
            include $view;
        } else {
            echo '<h1>' . $code . ' ' . htmlspecialchars($title) . '</h1><p>' . htmlspecialchars($message) . '</p>';
        }
        exit;
    }

    public static function download(string $path, string $filename, ?string $mime = null, bool $deleteAfter = false): void
    {
        if (!is_file($path)) self::abort(404, 'Berkas tidak ditemukan.');
        $mime = $mime ?: (function_exists('mime_content_type') ? (mime_content_type($path) ?: 'application/octet-stream') : 'application/octet-stream');
        while (ob_get_level() > 0) ob_end_clean();
        header('Content-Description: File Transfer');
        header('Content-Type: ' . $mime);
        header('Content-Disposition: attachment; filename="' . str_replace('"', '', $filename) . '"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . filesize($path));
        header('Cache-Control: must-revalidate, no-store, no-cache, private');
        header('Pragma: public');
        readfile($path);
        if ($deleteAfter) @unlink($path);
        exit;
    }

    public static function sendString(string $content, string $filename, string $mime): void
    {
        while (ob_get_level() > 0) ob_end_clean();
        header('Content-Type: ' . $mime);
        header('Content-Disposition: attachment; filename="' . str_replace('"', '', $filename) . '"');
        header('Content-Length: ' . strlen($content));
        header('Cache-Control: must-revalidate, no-store, no-cache, private');
        echo $content;
        exit;
    }

    public static function securityHeaders(): void
    {
        header('X-Content-Type-Options: nosniff');
        header('X-Frame-Options: SAMEORIGIN');
        header('Referrer-Policy: strict-origin-when-cross-origin');
        header('X-XSS-Protection: 1; mode=block');
        header_remove('X-Powered-By');
    }
}
