<?php

namespace MintyPHP\Service\Settings;

use MintyPHP\I18n;

/**
 * App-wide (global) settings gateway.
 *
 * Appearance SETTINGS (theme, user-theme toggle, primary color) are NOT
 * managed globally — they live on the tenant (tenants.primary_color,
 * default_theme, allow_user_theme) and are resolved by branding helpers.
 *
 * The theme CATALOG utilities (listThemes, isAllowedTheme, normalizeTheme,
 * resolveDefaultTheme) stay because consumers across Tenant / Auth / User
 * flows need to validate a theme value and resolve a safe default. The
 * catalog is a fixed two-entry list; 'light' is the hardcoded default.
 */
class SettingsAppGateway
{
    private const THEMES = [
        'light' => 'Light',
        'dark' => 'Dark',
    ];

    public function __construct(
        private readonly SettingsMetadataGateway $settingsMetadataGateway,
    ) {
    }

    public function getAppTitle(): ?string
    {
        $value = $this->settingsMetadataGateway->getValue(SettingKeys::APP_TITLE_KEY);
        $value = $value !== null ? trim($value) : null;
        return $value !== '' ? $value : null;
    }

    public function setAppTitle(?string $title, ?string $description = null): bool
    {
        $value = $title !== null ? trim($title) : null;
        if ($value === '') {
            $value = null;
        }

        $desc = $description ?? 'setting.app_title';
        return $this->settingsMetadataGateway->set(SettingKeys::APP_TITLE_KEY, $value, $desc);
    }

    public function getAppLocale(): ?string
    {
        $value = $this->settingsMetadataGateway->getValue(SettingKeys::APP_LOCALE_KEY);
        $value = $value !== null ? trim($value) : '';
        return $value !== '' ? $value : null;
    }

    public function setAppLocale(?string $locale, ?string $description = null): bool
    {
        $value = $locale !== null ? trim($locale) : '';
        if ($value === '') {
            $value = null;
        } else {
            $allowed = defined('APP_LOCALES') ? APP_LOCALES : [];
            if ($allowed && !in_array($value, $allowed, true)) {
                return false;
            }
        }

        $desc = $description ?? 'setting.app_locale';
        return $this->settingsMetadataGateway->set(SettingKeys::APP_LOCALE_KEY, $value, $desc);
    }

    public function isRegistrationEnabled(): bool
    {
        return settingToBool(
            $this->settingsMetadataGateway->getValue(SettingKeys::APP_REGISTRATION_KEY),
            true
        );
    }

    public function setRegistrationEnabled(bool $allowed, ?string $description = null): bool
    {
        $value = $allowed ? '1' : '0';
        $desc = $description ?? 'setting.app_registration';
        return $this->settingsMetadataGateway->set(SettingKeys::APP_REGISTRATION_KEY, $value, $desc);
    }

    /**
     * @return array<string, string>
     */
    public function listThemes(): array
    {
        return self::THEMES;
    }

    public function isAllowedTheme(?string $theme): bool
    {
        $value = strtolower(trim((string) $theme));
        return $value !== '' && in_array($value, $this->allowedThemes(), true);
    }

    /**
     * Default theme for flows that need ONE value without a tenant context
     * (user creation defaults, SSO-linked account provisioning, etc.).
     * Hardcoded to 'light' with a catalog fallback — no global setting.
     */
    public function resolveDefaultTheme(): string
    {
        $allowed = $this->allowedThemes();
        if (in_array('light', $allowed, true)) {
            return 'light';
        }

        return (string) ($allowed[0] ?? 'light');
    }

    public function normalizeTheme(?string $theme): string
    {
        $value = strtolower(trim((string) $theme));
        if ($this->isAllowedTheme($value)) {
            return $value;
        }

        return $this->resolveDefaultTheme();
    }

    public function normalizeLocale(?string $locale): string
    {
        $value = strtolower(trim((string) $locale));
        $available = defined('APP_LOCALES') ? APP_LOCALES : [I18n::$defaultLocale];
        if ($value === '' || !in_array($value, $available, true)) {
            return I18n::$locale ?? I18n::$defaultLocale;
        }

        return $value;
    }

    /**
     * @return list<string>
     */
    private function allowedThemes(): array
    {
        return array_keys($this->listThemes());
    }
}
