import { AppConfig } from './config-schema.js';
import { FeatureManifest } from '@camstack/types';
export interface AddonSettingsView {
    readAddonStore(): Promise<Record<string, unknown>>;
    writeAddonStore(patch: Record<string, unknown>): Promise<void>;
    readDeviceStore(deviceId: number): Promise<Record<string, unknown>>;
    writeDeviceStore(deviceId: number, patch: Record<string, unknown>): Promise<void>;
    clearDeviceStore(deviceId: number): Promise<void>;
    getSection(section: string): Promise<Record<string, unknown>>;
    setSection(section: string, patch: Record<string, unknown>): Promise<void>;
    /**
     * Per-device runtime state — separate namespace from
     * `readDeviceStore` / `writeDeviceStore` (which is the addon's
     * config blob: host, password, deviceCache, …). Holds mutable
     * runtime signals discovered after boot: battery snapshot, sleep
     * flag, last-seen timestamps. Stored under a kernel-internal
     * `__device-state` namespace so the device's config schema
     * never has to know about it (clean separation of operator
     * intent from runtime telemetry).
     *
     * Patch semantics: shallow merge. Pass the FULL persistent slice
     * each call (the kernel doesn't try to compute deltas) — concrete
     * implementations of `DeviceRuntimeState` already coalesce in
     * memory, so the kernel just persists the latest blob.
     */
    readDeviceRuntimeState(deviceId: number): Promise<Record<string, unknown>>;
    writeDeviceRuntimeState(deviceId: number, data: Record<string, unknown>): Promise<void>;
    clearDeviceRuntimeState(deviceId: number): Promise<void>;
}
export interface ISettingsStore {
    getSystem(key: string): unknown;
    setSystem(key: string, value: unknown): void;
    getAllSystem(): Record<string, unknown>;
    /** Addon-level global settings (apply to every device unless overridden). */
    getAllAddon(addonId: string): Record<string, unknown>;
    setAllAddon(addonId: string, config: Record<string, unknown>): void;
    /** Legacy per-provider settings (used by some older wiring paths). */
    getAllProvider(providerId: string): Record<string, unknown>;
    setProvider(providerId: string, key: string, value: unknown): void;
    /** Legacy flat per-device settings. Kept for backward compatibility
     *  with pre-addon wiring; new code should use the addon-device API. */
    getAllDevice(deviceId: string): Record<string, unknown>;
    setDevice(deviceId: string, key: string, value: unknown): void;
    /**
     * Multi-level addon settings: per-device overrides for a specific addon.
     *
     * Resolution chain when the frontend asks for the effective value of a
     * field on a given device:
     *   1. schema default (from `ConfigUISchema.field.default`)
     *   2. `getAllAddon(addonId)`           — addon global value
     *   3. `getAddonDevice(addonId, devId)` — per-device override (wins)
     *
     * Only fields declared with `scope: 'device'` in the addon's
     * `ConfigUISchema` should ever be persisted here.
     */
    getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
    setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
    clearAddonDevice(addonId: string, deviceId: string): void;
}
export declare class ConfigManager {
    private readonly configPath;
    private bootstrapConfig;
    private settingsStore;
    private runtimeState;
    private readonly runtimeStatePath;
    constructor(configPath: string);
    /**
     * Wire the settings-store backend. Called once, after the `settings-store`
     * capability provider has registered (normally during Phase-1 infra boot).
     * Before this call, runtime reads/writes fall back to bootstrap + defaults.
     */
    setSettingsStore(store: ISettingsStore): void;
    /**
     * Get a config value by dot-notation path.
     * Priority: bootstrap config (yaml) → settings-store → RUNTIME_DEFAULTS fallback.
     *
     * Returns `unknown` — callers must narrow via `typeof`/type guards, OR use
     * the generic overload at their own risk. The generic overload exists only
     * as a convenience alias for legacy call sites; it performs NO runtime
     * check and is the one documented type-level bridge in this function.
     */
    get(path: string): unknown;
    get<T>(path: string): T | undefined;
    private resolveConfigValue;
    /**
     * Write a value to the settings-store.
     * Throws if the settings store is not yet wired.
     */
    set(key: string, value: unknown): void;
    /**
     * Bulk-read all keys that belong to a logical section.
     * A "section" is the first segment of a dot-notation key (e.g. 'features', 'logging').
     *
     * Sources are merged in priority order (lowest → highest):
     *   1. RUNTIME_DEFAULTS — kernel constants.
     *   2. Bootstrap config  — values loaded from config.yaml at boot.
     *   3. Settings-store    — runtime writes via the `settings-store` capability.
     *
     * Higher layers override earlier ones. Merging (instead of short-circuiting
     * on the first non-null source) prevents a single store-seeded key from
     * shadowing the rest of the section that only lives in config.yaml.
     * The kernel is agnostic about the store backend — any `ISettingsStore`
     * implementation (sqlite, redis, in-memory, …) behaves identically here.
     */
    getSection(section: string): Record<string, unknown>;
    /**
     * Bulk-write a logical section to the settings-store.
     * Each entry in `data` is persisted under the key `section.<entryKey>`.
     */
    setSection(section: string, data: Record<string, unknown>): void;
    /** Read all config for an addon from addon_settings. */
    getAddonConfig(addonId: string): Record<string, unknown>;
    /** Write (bulk-replace) config for an addon to addon_settings. */
    setAddonConfig(addonId: string, config: Record<string, unknown>): void;
    /** Read all config for a provider from provider_settings. */
    getProviderConfig(providerId: string): Record<string, unknown>;
    /** Write (upsert) a single key for a provider to provider_settings. */
    setProviderConfig(providerId: string, key: string, value: unknown): void;
    /** Read all config for a device from device_settings. */
    getDeviceConfig(deviceId: string): Record<string, unknown>;
    /** Write (upsert) a single key for a device to device_settings. */
    setDeviceConfig(deviceId: string, key: string, value: unknown): void;
    /**
     * Read per-device overrides for a specific addon. Returns a flat record
     * of field → value. Missing keys fall back to the addon-global value via
     * `getAddonConfig(addonId)` — that composition is the resolver service's
     * responsibility, not ConfigManager's.
     */
    getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
    /**
     * Write (bulk-replace) per-device overrides for a specific addon.
     * Throws if the settings store is not yet wired.
     */
    setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
    /**
     * Clear all per-device overrides for a specific addon/device pair.
     * Resolution falls back to the addon-global value after this call.
     * No-op if the settings store is not yet wired.
     */
    clearAddonDevice(addonId: string, deviceId: string): void;
    createSettingsView(addonId: string): AddonSettingsView;
    /** Get all system-wide activation overrides. */
    getSystemActivation(): Readonly<Record<string, boolean>>;
    /** Set system-wide activation for a capability/addon pair. */
    setSystemActivation(capability: string, addonId: string, active: boolean): void;
    /**
     * Get activation overrides for a device.
     * Returns a map of `{capability}/{addonId}` → active boolean.
     * Missing entries mean "use system activation or autoActivate default".
     */
    getDeviceActivation(deviceId: string): Readonly<Record<string, boolean>>;
    /**
     * Get all device activation overrides.
     * Returns deviceId → (`{capability}/{addonId}` → active).
     */
    getAllDeviceActivation(): Readonly<Record<string, Record<string, boolean>>>;
    /**
     * Set activation for a specific capability/addon on a device.
     * Persists immediately to runtime-state.json.
     *
     * @param deviceId - The device to configure
     * @param capability - Capability name (e.g., 'motion-detection')
     * @param addonId - Addon providing the capability (e.g., 'wasm-motion')
     * @param active - Whether the capability is active on this device
     */
    setDeviceActivation(deviceId: string, capability: string, addonId: string, active: boolean): void;
    /**
     * Clear all activation overrides for a device (resets to autoActivate defaults).
     */
    clearDeviceActivation(deviceId: string): void;
    /** Get a value from the parsed bootstrap config.
     *  Generic overload is a documented type-level bridge — callers are responsible
     *  for passing a T that matches the config.yaml shape. */
    getBootstrap(path: string): unknown;
    getBootstrap<T>(path: string): T | undefined;
    /** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
    get features(): FeatureManifest;
    /**
     * Returns a merged view of bootstrap config + runtime defaults for backward compat.
     */
    get raw(): AppConfig;
    /** Sections that live in config.yaml. Everything else goes to the settings-store. */
    private static readonly BOOTSTRAP_SECTIONS;
    /**
     * Atomically update one top-level section of config.yaml and sync in-memory.
     * Only bootstrap sections (server, auth, mode) are written to YAML.
     * Runtime settings must use setSection() which writes to the settings-store.
     */
    update(section: string, data: Record<string, unknown>): void;
    /**
     * Deep-set a value in a nested plain object using a dot-notation path.
     * Returns a new object (immutable).
     */
    private setNested;
    /**
     * Apply env var overrides onto the raw YAML object.
     * Only bootstrap-level env vars are applied.
     */
    private applyEnvOverrides;
    private loadYaml;
    private warnDefaultCredentials;
    private getFromBootstrap;
    private getFromRuntimeDefaults;
    /**
     * Perform a prefix-based nested lookup against the settings-store.
     * e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
     * Returns an object keyed by the sub-key, or undefined if nothing is found.
     */
    private getNestedFromSystemSettings;
    private loadRuntimeState;
    private saveRuntimeState;
}
//# sourceMappingURL=config-manager.d.ts.map