<?php

declare(strict_types=1);

namespace ShieldX\Maintenance;

defined('ABSPATH') || exit;

use ShieldX\Core\RequestCache;

final class BackupStorageSettings
{
    public const OPTION_NAME = 'shieldx_backup_storage_settings';
    public const MODE_LOCAL = 'local';
    public const MODE_GOOGLE = 'google';
    public const MODE_BOTH = 'both';

    /** @var array<string,mixed> */
    private $settings;

    /**
     * @param array<string,mixed> $settings
     */
    public function __construct(array $settings = [])
    {
        $this->settings = self::normalize($settings);
    }

    public static function fromWordPress(): self
    {
        $cached = RequestCache::get(self::class);
        if ($cached instanceof self) {
            return $cached;
        }

        $stored = function_exists('get_option') ? get_option(self::OPTION_NAME, []) : [];

        $instance = new self(is_array($stored) ? $stored : []);
        RequestCache::rememberOption(self::class, self::OPTION_NAME, $instance);

        return $instance;
    }

    /**
     * @return array<string,mixed>
     */
    public function all(): array
    {
        return $this->settings;
    }

    public function mode(): string
    {
        return (string) ($this->settings['mode'] ?? self::MODE_LOCAL);
    }

    public function usesGoogle(): bool
    {
        return in_array($this->mode(), [self::MODE_GOOGLE, self::MODE_BOTH], true);
    }

    public function keepsLocal(): bool
    {
        return $this->mode() !== self::MODE_GOOGLE;
    }

    /**
     * @param array<string,mixed> $settings
     */
    public function save(array $settings): void
    {
        $this->settings = self::normalize(array_merge($this->settings, $settings));

        if (function_exists('update_option')) {
            update_option(self::OPTION_NAME, $this->settings, false);
        }

        RequestCache::rememberOption(self::class, self::OPTION_NAME, $this);
    }

    /**
     * @param array<string,mixed> $settings
     * @return array<string,mixed>
     */
    private static function normalize(array $settings): array
    {
        $mode = isset($settings['mode']) ? self::sanitizeMode((string) $settings['mode']) : self::MODE_LOCAL;

        return [
            'mode' => $mode,
        ];
    }

    public static function sanitizeMode(string $mode): string
    {
        $mode = function_exists('sanitize_key') ? sanitize_key($mode) : strtolower(preg_replace('/[^a-z0-9_\-]/', '', $mode) ?: '');

        return in_array($mode, [self::MODE_LOCAL, self::MODE_GOOGLE, self::MODE_BOTH], true) ? $mode : self::MODE_LOCAL;
    }
}
