import * as React from 'react';
import { P as Product } from '../app-store-B5t8W1GX.js';
import { ProductBrandConfig } from './product-brand.js';
import 'zustand/middleware';
import 'zustand';
import './custom-product-defaults.js';

/**
 * Product registry — the public surface for customer apps to declare their
 * own products. The DS owns the shell (sidebar chrome, product switcher,
 * settings → appearance, route guards); customers register products
 * (id, slug, label, brand, nav, scope) and the DS sidebar wires them in.
 *
 * Usage in a customer app's bootstrap (e.g. `src/main.tsx`):
 *
 * ```tsx
 * import {
 *   defineProduct,
 *   registerProducts,
 * } from "@exxatdesignux/ui/product-framework"
 *
 * const survey = defineProduct({
 *   id: "exxat-survey",
 *   slug: "survey",
 *   label: "Exxat Survey",
 *   brandSuffix: "Survey",
 *   brandColor: "oklch(0.62 0.20 200)",
 *   scope: "school-program",
 *   nav: [
 *     { key: "dashboard", title: "Dashboard", url: "/survey/dashboard",
 *       icon: <i className="fa-light fa-gauge-high" aria-hidden /> },
 *     { key: "surveys", title: "Surveys", url: "/survey/surveys",
 *       icon: <i className="fa-light fa-clipboard-list" aria-hidden /> },
 *   ],
 * })
 *
 * registerProducts([survey])
 * ```
 *
 * Adding a new product is one file change in the customer app. No DS
 * version bump required.
 *
 * What the registry does NOT own:
 *  - **Routes** — the customer app's router (`react-router-dom`, TanStack
 *    Router, anything) maps `/<slug>/*` → React elements. The registry only
 *    knows the slug; the customer wires the routes.
 *  - **Data** — mock data, API clients, server state. Out of scope for the DS.
 *  - **Flows** — wizards, drawer compositions, dialogs. Owned by the customer.
 */

/**
 * One row in the primary sidebar nav. Mirrors the existing `NavLinkItem`
 * shape used by `apps/web/lib/mock/navigation.tsx` so apps can move existing
 * nav data into `defineProduct(...)` without reshaping.
 */
interface ProductNavLink {
    /** Stable identifier — used by `data-active` and React keys. */
    key: string;
    /** Visible label in the sidebar. */
    title: string;
    /** Destination URL. Should start with `/<product.slug>/...`. */
    url: string;
    /** Icon — typically a Font Awesome `<i className="fa-light ..." aria-hidden />` JSX node. */
    icon: React.ReactNode;
    /** Optional swapped icon when the link is active (solid vs light). */
    iconActive?: React.ReactNode;
    /** Optional child links — renders as a collapsible sub-menu. */
    children?: ProductNavLink[];
    /**
     * Optional inline badge — number for counts, or string label.
     * Special string values get distinct colors: `"New"` → green, `"Beta"` → amber.
     */
    badge?: number | string;
    /**
     * When this collapsible section uses `SecondaryPanel`, set the panel id so
     * child links can reopen the panel on click while already on the same route.
     */
    secondaryPanel?: string;
    /**
     * When several children share the same `url` (hub route), only this child's
     * key receives `data-active` for that pathname — otherwise every sub-row
     * looks selected.
     */
    primaryHubChildKey?: string;
}
/**
 * Scope hierarchy that a product runs under. Drives the team / scope picker
 * in the sidebar header (which fields it shows: school > program vs. brand >
 * site > location, etc.).
 *
 * If a customer's product needs a bespoke scope chrome, use `"custom"` and
 * supply your own header content via the `scopeRenderer` slot (added in C3).
 */
type ProductScope = "school-program" | "brand-site-location" | "school-batch-student" | "custom";
/**
 * Input shape accepted by {@link defineProduct}. Required: id, slug, label,
 * brandSuffix, brandColor, scope, nav. Everything else is optional with
 * sensible defaults (see {@link ProductDefinition} for the resolved shape).
 */
interface ProductDefinitionInput {
    /**
     * Stable product id — used in the Zustand store and the switcher. For
     * customer-defined products, prefix with the company name to avoid
     * collisions with future Exxat products (e.g. `"acme-vault"`, not just
     * `"vault"`).
     */
    id: string;
    /**
     * URL slug — the leading path segment owned by this product. MUST be
     * kebab-case, MUST NOT collide with shell-global segments (`/settings`,
     * `/library`, …) or existing built-in slugs (`prism`, `one-schools`,
     * `one-sites`, `custom`). The DS guards this at registration time.
     */
    slug: string;
    /** Human-readable label shown in the product switcher and settings list. */
    label: string;
    /**
     * Wordmark prefix. Defaults to `"Exxat"` so registered products read as
     * "Exxat <suffix>" by default. Pass an empty string `""` for a custom
     * customer brand (e.g. "Vault" with no Exxat prefix).
     */
    brandPrefix?: string;
    /** Wordmark suffix — the italic Ivy Presto part of the logo. */
    brandSuffix: string;
    /** Theme accent — drives chrome tints, links, focus rings. Any CSS color. */
    brandColor: string;
    /**
     * Optional logo-art override. By default, registered products inherit
     * the Exxat pink mark + gradient + shadow (corporate identity stays
     * consistent across all products). Supply any subset to override.
     */
    brand?: Partial<ProductBrandConfig>;
    /** Primary sidebar nav for this product. */
    nav: ProductNavLink[];
    /**
     * Scope hierarchy this product runs under. Drives the sidebar header
     * picker (school > program vs. brand > site > location, etc.).
     */
    scope: ProductScope;
    /**
     * Default landing path after switching to this product. Defaults to
     * `/<slug>/dashboard`.
     */
    defaultPath?: string;
}
/** Resolved product definition with defaults applied. */
interface ProductDefinition extends ProductDefinitionInput {
    brandPrefix: string;
    defaultPath: string;
}
/**
 * Build a {@link ProductDefinition} from input. Applies defaults but does
 * NOT register — call {@link registerProducts} when you're ready to wire
 * it into the sidebar.
 */
declare function defineProduct(input: ProductDefinitionInput): ProductDefinition;
/**
 * Register one or more products. Idempotent — re-registering an id replaces
 * the previous definition (useful for hot-reload). The function also mirrors
 * each product's wordmark into the brand registry so `brandForProduct(id)`
 * resolves correctly.
 */
declare function registerProducts(products: ProductDefinition[]): void;
/** All registered products in registration order. */
declare function listRegisteredProducts(): readonly ProductDefinition[];
/** Look up a product by id (e.g. `"exxat-prism"`). */
declare function getRegisteredProduct(id: string): ProductDefinition | undefined;
/** Look up a product by URL slug (e.g. `"prism"`). */
declare function getRegisteredProductBySlug(slug: string): ProductDefinition | undefined;
/**
 * Type-narrow a string to a registered product id. Returns the matching
 * {@link Product} from the built-in union when the id is one of the four
 * DS products, otherwise returns `undefined`. Customer-registered products
 * (e.g. `"exxat-survey"`) intentionally return `undefined` here because the
 * Zustand store's `Product` union is fixed to the DS-shipped four. Use
 * {@link getRegisteredProduct} to validate any registered id.
 */
declare function asBuiltInProduct(id: string): Product | undefined;
/**
 * Test-only: clear the registry. Never call this in production code — the
 * registry is intended to be filled once at app bootstrap and read-only
 * for the lifetime of the process.
 */
declare function __resetProductRegistry(): void;

export { type ProductDefinition, type ProductDefinitionInput, type ProductNavLink, type ProductScope, __resetProductRegistry, asBuiltInProduct, defineProduct, getRegisteredProduct, getRegisteredProductBySlug, listRegisteredProducts, registerProducts };
