<?php

declare(strict_types=1);

namespace CalendarPlugin\Domain;

use CalendarPlugin\Contracts\OptionsAdapterInterface;

final class SettingsService
{
    private const TRUE_VALUES = ['1', 'true', 'yes', 'on'];

    public const DEFAULTS = [
        'caldav_calendar_name' => 'Public Calendar',
        'url_slug' => '',
        'verification_page_path' => '/calendar',
        'ics_access_mode' => 'public_read',
        'diagnostics_enabled' => '1',
        'uninstall_cleanup_mode' => 'keep',
    ];

    private const OPTION_PREFIX = 'calendar_plugin_';

    public function __construct(private readonly OptionsAdapterInterface $options)
    {
    }

    public function getAll(): array
    {
        $out = [];
        foreach (self::DEFAULTS as $key => $default) {
            $out[$key] = $this->get($key, $default);
        }
        return $out;
    }

    public function get(string $key, mixed $default = null): mixed
    {
        $fallback = $default ?? (self::DEFAULTS[$key] ?? null);
        return $this->options->get(self::OPTION_PREFIX . $key, $fallback);
    }

    public function update(array $payload): array
    {
        $allowed = array_keys(self::DEFAULTS);
        $updated = $this->getAll();

        foreach ($allowed as $key) {
            if (!array_key_exists($key, $payload)) {
                continue;
            }
            $value = $this->sanitize($key, $payload[$key]);
            $this->options->set(self::OPTION_PREFIX . $key, $value);
            $updated[$key] = $value;
        }

        return $updated;
    }

    private function sanitize(string $key, mixed $value): mixed
    {
        return match ($key) {
            'caldav_calendar_name' => trim((string) $value) ?: self::DEFAULTS[$key],
            'url_slug' => trim((string) $value, " \t\n\r\0\x0B/"),
            'verification_page_path' => $this->normalizePath((string) $value),
            'ics_access_mode' => in_array((string) $value, ['public_read', 'authenticated_read'], true)
                ? (string) $value
                : self::DEFAULTS['ics_access_mode'],
            'diagnostics_enabled' => $this->isTruthy($value) ? '1' : '0',
            'uninstall_cleanup_mode' => in_array((string) $value, ['keep', 'remove'], true) ? (string) $value : 'keep',
            default => $value,
        };
    }

    private function isTruthy(mixed $value): bool
    {
        return in_array(strtolower(trim((string) $value)), self::TRUE_VALUES, true);
    }

    private function normalizePath(string $value): string
    {
        $path = trim($value);
        if ($path === '') {
            return self::DEFAULTS['verification_page_path'];
        }
        if (!str_starts_with($path, '/')) {
            $path = '/' . $path;
        }
        return '/' . trim($path, '/');
    }
}
