<?php
/**
 * Reads and writes Bricks page settings (`_bricks_page_settings`).
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Gateways;

use LolaCoreForBricks\Support\BricksMetaKeys;
use LolaCoreForBricks\Support\CssRegenerator;
use LolaCoreForBricks\Support\CssTextGuard;
use LolaCoreForBricks\Support\PageSettingsKeys;

/**
 * Persists page-level settings. Template conditions stay in B11.
 */
class PageSettingsGateway
{
    public function __construct(
        private readonly ?CssRegenerator $cssRegenerator = null
    ) {
    }

    /**
     * @return array<string, mixed>
     */
    public function read(int $postId): array
    {
        if ($postId <= 0) {
            return [];
        }

        $settings = get_post_meta($postId, BricksMetaKeys::PAGE_SETTINGS, true);

        return is_array($settings) ? $settings : [];
    }

    /**
     * @param array<string, mixed> $settings
     * @return array<string, mixed>
     */
    public function write(int $postId, array $settings, bool $dryRun = false): array
    {
        if ($postId <= 0 || get_post($postId) === null) {
            return [
                'success' => false,
                'message' => 'I could not find that page. It may have been deleted.',
                'error'   => 'post_not_found',
            ];
        }

        $guarded = $this->guardSettings($settings);
        if ($guarded !== null) {
            return $guarded;
        }

        $current = $this->read($postId);
        $merged  = array_merge($current, $settings);
        foreach (array_keys($settings) as $key) {
            if ($settings[$key] === null) {
                unset($merged[$key]);
            }
        }

        if ($dryRun) {
            return [
                'success'  => true,
                'dry_run'  => true,
                'message'  => 'Page settings preview is ready.',
                'post_id'  => $postId,
                'settings' => $merged,
            ];
        }

        update_post_meta($postId, BricksMetaKeys::PAGE_SETTINGS, $merged);
        ($this->cssRegenerator ?? new CssRegenerator())->afterPageSettings($postId);

        return [
            'success'  => true,
            'message'  => 'I updated the page settings. Refresh the front to see them.',
            'post_id'  => $postId,
            'settings' => $merged,
        ];
    }

    /**
     * @param array<string, mixed> $settings
     * @return array{success: false, message: string, error: string}|null
     */
    public function guardSettings(array $settings): ?array
    {
        foreach ($settings as $key => $_value) {
            $key = (string) $key;
            if (PageSettingsKeys::isForbidden($key)) {
                return [
                    'success' => false,
                    'message' => $key === 'templateConditions'
                        ? 'Template conditions belong to the template, not the page. Use updateTemplateConditions for that.'
                        : 'I cannot save page scripts or code from here. Remove that setting and try again.',
                    'error'   => $key === 'templateConditions' ? 'template_conditions_forbidden' : 'forbidden_code',
                ];
            }

            if (PageSettingsKeys::isCssKey($key) && is_string($settings[$key])) {
                $css = CssTextGuard::rejectionResponse($settings[$key]);
                if ($css !== null) {
                    return $css;
                }
            }
        }

        return null;
    }
}
