<?php
// core/Controller.php

class Controller {
    protected Database $db;

    public function __construct() {
        $this->db = Database::getInstance();
    }

    protected function view(string $view, array $data = [], ?string $layout = 'main'): void {
        extract($data);
        $viewFile = APP_ROOT . '/app/views/' . str_replace('.', '/', $view) . '.php';

        if (!file_exists($viewFile)) {
            die("View not found: $viewFile");
        }

        if ($layout) {
            $layoutFile = APP_ROOT . '/app/views/layouts/' . $layout . '.php';
            if (file_exists($layoutFile)) {
                // Capture view content
                ob_start();
                require $viewFile;
                $content = ob_get_clean();
                require $layoutFile;
                return;
            }
        }

        require $viewFile;
    }

    protected function json(mixed $data, int $code = 200): void {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    protected function redirect(string $url): void {
        // Flush session ke disk sebelum redirect agar data tidak hilang
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_write_close();
        }
        header("Location: $url");
        exit;
    }

    protected function back(): void {
        $referer = $_SERVER['HTTP_REFERER'] ?? APP_URL;
        $this->redirect($referer);
    }

    protected function csrf(): string {
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        return $_SESSION['csrf_token'];
    }

    protected function verifyCsrf(): bool {
        // Pastikan session aktif sebelum membaca token
        Auth::init();
        $token = $_POST['_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
        return hash_equals($_SESSION['csrf_token'] ?? '', $token);
    }

    protected function input(string $key, mixed $default = null): mixed {
        return $_POST[$key] ?? $_GET[$key] ?? $default;
    }

    protected function sanitize(string $value): string {
        return htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
    }

    protected function flash(string $type, string $message, array $extra = []): void {
        $_SESSION['flash'] = ['type' => $type, 'message' => $message] + $extra;
    }

    protected function getFlash(): ?array {
        if (isset($_SESSION['flash'])) {
            $flash = $_SESSION['flash'];
            unset($_SESSION['flash']);
            return $flash;
        }
        return null;
    }

    protected function uploadFile(array $file, string $dir = 'uploads'): ?string {
        if ($file['error'] !== UPLOAD_ERR_OK) return null;

        $ext   = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $allow = ['jpg', 'jpeg', 'png', 'webp'];
        if (!in_array($ext, $allow)) return null;

        $maxSize = 5 * 1024 * 1024; // 5MB
        if ($file['size'] > $maxSize) return null;

        $filename = uniqid('img_', true) . '.' . $ext;
        $destDir  = APP_ROOT . '/public/images/' . $dir . '/';
        if (!is_dir($destDir)) mkdir($destDir, 0755, true);

        if (move_uploaded_file($file['tmp_name'], $destDir . $filename)) {
            return $filename;
        }
        return null;
    }

    protected function paginate(int $total, int $perPage = 20): array {
        $page    = max(1, (int)($_GET['page'] ?? 1));
        $offset  = ($page - 1) * $perPage;
        $pages   = (int)ceil($total / $perPage);
        return compact('page', 'offset', 'perPage', 'pages', 'total');
    }
}