import { CustomProductBrand } from './product-framework/custom-product-defaults.js';
import { ProductScope, ProductDefinition } from './product-framework/product-registry.js';

/**
 * Tenant product store — serializable shapes for permanent browser-local
 * persistence (survives Cloudflare deploys; cleared only on explicit delete).
 */

declare const TENANT_STORE_KEY = "tenant-store:v1";
declare const TENANT_STORE_VERSION = 1;
declare const TENANT_PRODUCT_DATA_VERSION = 1;
/** Nav row storable in localStorage (icons as FA class strings). */
interface SerializableNavLink {
    key: string;
    title: string;
    url: string;
    iconClass: string;
    iconActiveClass?: string;
    badge?: number | string;
    secondaryPanel?: string;
    primaryHubChildKey?: string;
    children?: SerializableNavLink[];
}
/**
 * Full product definition persisted for Settings and `defineProduct` parity.
 * `source: "user"` — created/edited in Settings. `source: "code"` — seeded from
 * `registerProducts()` at bootstrap (user edits on user fields are preserved).
 */
interface TenantProductRecord {
    id: string;
    slug: string;
    label: string;
    brandPrefix: string;
    brandSuffix: string;
    brandColor: string;
    scope: ProductScope;
    nav: SerializableNavLink[];
    defaultPath: string;
    source: "user" | "code";
    createdAt: string;
    updatedAt: string;
    /** Soft-delete — hidden from switcher until purged. */
    deletedAt?: string | null;
    /** Forward-compatible bag for future DS capabilities. */
    extensions?: Record<string, unknown>;
}
/**
 * Per-product data document — all domain + hub payloads for one product.
 * Prefer writing new capabilities under `extensions` or typed sections below.
 */
interface TenantProductDataBag {
    v: number;
    /** Hub/table/page persisted slices (structured by consumer). */
    hubs: Record<string, unknown>;
    /** Entity collections (library items, placements, …). */
    entities: Record<string, unknown>;
    /** Product-level preferences not tied to a hub. */
    preferences: Record<string, unknown>;
    /**
     * Raw legacy `exxat-ds:<slug>:…` values imported during migration so nothing
     * is lost when upgrading from pre–tenant-store packages.
     */
    legacy: Record<string, string>;
    /** Open-ended capability storage. */
    extensions: Record<string, unknown>;
}
interface TenantStoreMeta {
    migratedFromCustomProducts?: boolean;
    migratedLegacyStorageKeys?: boolean;
    lastMigrationAt?: string;
}
interface TenantStore {
    v: number;
    catalog: TenantProductRecord[];
    products: Record<string, TenantProductDataBag>;
    /** `customProducts[i]` → `catalog[].id` after migration from app-store v9. */
    legacyCustomIndexMap?: string[];
    meta: TenantStoreMeta;
}
declare function emptyProductDataBag(): TenantProductDataBag;
declare function emptyTenantStore(): TenantStore;

/**
 * Read / write arbitrary per-product data inside the tenant store.
 */

declare function getTenantProductData<T>(productId: string, path: string, defaultValue: T): T;
declare function setTenantProductData(productId: string, path: string, value: unknown, options?: {
    debounceMs?: number;
}): void;
/** Import a legacy `exxat-ds:` value into the product bag (idempotent). */
declare function importLegacyKeyIntoProduct(productId: string, relativeKey: string, rawValue: string): void;
declare function removeTenantProductData(productId: string): void;
declare function readTenantProductDataBag(productId: string): TenantProductDataBag | null;
/**
 * Dual-write helper: persist structured data AND keep legacy key for older
 * package versions until fully migrated.
 */
declare function setTenantProductDataWithLegacyMirror(productId: string, path: string, value: unknown, legacyStorageKey?: string): void;
declare function getTenantProductDataFromLegacyOrBag<T>(productId: string, path: string, legacyStorageKey: string | undefined, defaultValue: T): T;

/**
 * One-time migration: `customProducts[]` + legacy `exxat-ds:<slug>:*` keys →
 * unified tenant store. Safe to run on every hydration (idempotent).
 */

/**
 * Upsert every Settings row into the tenant catalog (idempotent by slug).
 * Runs on every hydration so `exxat-app` and `tenant-store:v1` stay aligned.
 */
declare function syncCustomProductsIntoCatalog(store: TenantStore, customProducts: CustomProductBrand[]): void;
interface TenantMigrationResult {
    store: TenantStore;
    /** Updated mirror for `useAppStore.customProducts`. */
    customProducts: CustomProductBrand[];
}
/**
 * Run all tenant-store migrations. Pass the hydrated `customProducts` array
 * from `useAppStore` so v9 installs upgrade without data loss.
 */
declare function runTenantProductMigration(customProducts: CustomProductBrand[]): TenantMigrationResult;
/** Remove a tenant product and its `exxat-ds:<slug>:*` legacy keys. */
declare function deleteTenantProductPermanently(productId: string): void;

/**
 * CRUD for tenant products — used by Settings and `registerProducts` merge.
 */

declare function listTenantProducts(): TenantProductRecord[];
declare function upsertUserTenantProductFromBrand(brand: CustomProductBrand): {
    index: number;
    record: TenantProductRecord;
};
declare function mergeCodeProductsIntoTenantStore(definitions: ProductDefinition[]): void;
declare function registerProductsFromTenantStore(): void;
declare function removeTenantProduct(productId: string): CustomProductBrand[];
declare function syncCustomProductsMirror(): CustomProductBrand[];

/**
 * Bootstrap hook — migrate legacy state, mirror `customProducts`, register
 * tenant catalog with the in-memory product registry.
 */

interface HydrateTenantProductsOptions {
    /** `customProducts` from hydrated `useAppStore`. */
    customProducts: CustomProductBrand[];
    /** Code-defined products from `registerProducts()` at app bootstrap. */
    codeProducts?: ProductDefinition[];
}
interface HydrateTenantProductsResult {
    customProducts: CustomProductBrand[];
}
/**
 * Call once after `useAppStore` rehydrates (e.g. in `ProductProvider`).
 * Idempotent — safe on every page load.
 */
declare function hydrateTenantProducts(options: HydrateTenantProductsOptions): HydrateTenantProductsResult;

export { syncCustomProductsMirror as A, type HydrateTenantProductsOptions as H, type SerializableNavLink as S, TENANT_STORE_KEY as T, TENANT_STORE_VERSION as a, type TenantProductDataBag as b, type TenantProductRecord as c, type TenantStore as d, deleteTenantProductPermanently as e, type HydrateTenantProductsResult as f, getTenantProductData as g, hydrateTenantProducts as h, TENANT_PRODUCT_DATA_VERSION as i, type TenantMigrationResult as j, type TenantStoreMeta as k, listTenantProducts as l, mergeCodeProductsIntoTenantStore as m, emptyProductDataBag as n, emptyTenantStore as o, getTenantProductDataFromLegacyOrBag as p, importLegacyKeyIntoProduct as q, readTenantProductDataBag as r, setTenantProductData as s, registerProductsFromTenantStore as t, upsertUserTenantProductFromBrand as u, removeTenantProduct as v, removeTenantProductData as w, runTenantProductMigration as x, setTenantProductDataWithLegacyMirror as y, syncCustomProductsIntoCatalog as z };
