<?php

namespace App\Core;

/**
 * ITSWEBER CMS – Base Controller
 */
abstract class Controller
{
    protected App $app;

    public function __construct(App $app)
    {
        $this->app = $app;
    }

    /**
     * Render a theme template and send it as HTML response.
     */
    protected function render(string $template, array $data = []): void
    {
        $view = $this->app->service('view');
        $content = $view->render($template, $data);
        Response::html($content);
    }

    /**
     * Render an admin view and send it as HTML response.
     */
    protected function renderAdmin(string $view, array $data = []): void
    {
        $viewEngine = $this->app->service('view');
        $content = $viewEngine->renderAdmin($view, $data);
        Response::html($content);
    }

    /**
     * Redirect to a URL.
     */
    protected function redirect(string $url): void
    {
        Response::redirect($url);
    }

    /**
     * Get the database instance.
     */
    protected function db(): Database
    {
        return $this->app->db();
    }

    /**
     * Get the session instance.
     */
    protected function session(): Session
    {
        return $this->app->service('session');
    }

    /**
     * Get the auth instance.
     */
    protected function auth(): Auth
    {
        return $this->app->service('auth');
    }

    /**
     * Get the CSRF instance.
     */
    protected function csrf(): Csrf
    {
        return $this->app->service('csrf');
    }

    /**
     * Validate CSRF token from POST request.
     */
    protected function validateCsrf(): void
    {
        $this->csrf()->check();
    }

    /**
     * Clear the file-based page cache and related caches.
     * Call this after any content/menu/theme change that affects frontend rendering.
     */
    protected function clearPageCache(): void
    {
        (new \App\Services\PageCache($this->app->basePath()))->clear();

        // Also invalidate the accessibility audit cache (results depend on content)
        $a11yCache = $this->app->basePath() . '/storage/cache/a11y_audit.json';
        if (is_file($a11yCache)) {
            @unlink($a11yCache);
        }
    }

    /**
     * Send ETag and Last-Modified headers based on content data.
     * If the client sends matching conditional headers, returns 304 and exits.
     *
     * Call this in frontend controllers before rendering when you have
     * the page/post record with an updated_at timestamp.
     */
    protected function sendContentCacheHeaders(string $updatedAt, string $contentHash = ''): void
    {
        if (setting('http_cache_enabled', '0') !== '1') {
            return;
        }

        // Skip for logged-in users
        if ($this->app->hasService('auth') && $this->auth()->check()) {
            return;
        }

        $lastModified = strtotime($updatedAt);
        if ($lastModified === false) {
            return;
        }

        $lastModifiedGmt = gmdate('D, d M Y H:i:s', $lastModified) . ' GMT';
        header('Last-Modified: ' . $lastModifiedGmt);

        // ETag from content hash or updated_at
        $etag = '"' . md5($updatedAt . $contentHash) . '"';
        header('ETag: ' . $etag);

        // Handle conditional requests (304 Not Modified)
        $ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? '';
        $ifNoneMatch     = $_SERVER['HTTP_IF_NONE_MATCH'] ?? '';

        if ($ifNoneMatch === $etag || ($ifModifiedSince && strtotime($ifModifiedSince) >= $lastModified)) {
            http_response_code(304);
            exit;
        }
    }
}
