import * as react from 'react';
import { ReactNode } from 'react';

/**
 * Parsed domain information derived from a request hostname.
 *
 * Used both on the Fastify request object (`request.domainInfo`) and in the
 * Unirend React context (`useDomainInfo()`).
 */
interface DomainInfo {
    /** Bare hostname with port stripped (IPv6-safe, e.g. `'app.example.com'` or `'::1'`). */
    hostname: string;
    /**
     * Apex domain without a leading dot (e.g. `'example.com'`).
     * Empty string for localhost and raw IP addresses where no root domain can be resolved.
     *
     * When empty, omit the `domain` attribute entirely — `domain=.localhost` is invalid
     * per RFC 6265 and browsers reject it. A cookie without a `domain` attribute becomes
     * a host-only cookie scoped to the exact hostname, which is correct for localhost and IPs.
     *
     * Prepend `.` when using as a cookie `domain` attribute to span subdomains:
     * ```ts
     * document.cookie = [
     *   'theme=dark',
     *   'path=/',
     *   'max-age=31536000',
     *   domainInfo.rootDomain ? `domain=.${domainInfo.rootDomain}` : null,
     * ].filter(Boolean).join('; ');
     * ```
     */
    rootDomain: string;
}

/**
 * Render mode type - SSR, SSG, or Client
 * - "ssr": Server-Side Rendering (runtime server rendering)
 * - "ssg": Static Site Generation (build-time server rendering)
 * - "client": Client-side execution (SPA or after a SSG build/SSR page hydration occurs)
 */
type UnirendRenderMode = 'ssr' | 'ssg' | 'client';
/**
 * Type guard to check if request has SSR helpers with request context
 */
declare function hasSSRRequestContext(request: Request): request is Request & {
    SSRHelpers: {
        fastifyRequest: {
            requestContext: Record<string, unknown>;
        };
    };
};
/**
 * Type guard to check if request has SSG helpers with request context
 */
declare function hasSSGRequestContext(request: Request): request is Request & {
    SSGHelpers: {
        requestContext: Record<string, unknown>;
    };
};
/**
 * Type guard to check if window has request context
 */
declare function hasWindowRequestContext(): boolean;
/**
 * Helper to get a value from request context storage
 * Works across SSR, SSG, and client environments
 */
declare function getRequestContextValue(context: UnirendContextValue, key: string): unknown;
/**
 * Helper to set a value in request context storage
 * Works across SSR, SSG, and client environments
 * Automatically increments the revision counter to trigger reactivity
 */
declare function setRequestContextValue(context: UnirendContextValue, key: string, value: unknown): void;
/**
 * Helper to increment the request context revision counter
 * Reads the current revision from context, parses it, and generates a new unique revision
 * Format: `${timestamp}-${counter}` (e.g., "1729123456789-0", "1729123456789-1")
 */
declare function incrementContextRevision(context: UnirendContextValue): void;
/**
 * Unirend context value type
 */
interface UnirendContextValue {
    /**
     * The render mode:
     * - 'ssr': Server-Side Rendering
     * - 'ssg': Static Site Generation
     * - 'client': Client-side execution (SPA or after a SSG build/SSR page hydration occurs)
     */
    renderMode: UnirendRenderMode;
    /**
     * Whether the app is running in development mode
     */
    isDevelopment: boolean;
    /**
     * The Fetch API Request object (available during SSR/SSG rendering)
     * Undefined on client-side after hydration
     */
    fetchRequest?: Request;
    /**
     * Public application configuration
     * This is a frozen (immutable) copy of the config passed to the server
     * Available on both server and client (injected into HTML during SSR/SSG)
     */
    publicAppConfig?: Record<string, unknown>;
    /**
     * CDN base URL for asset serving (e.g. 'https://cdn.example.com')
     * Available on both server (from app config or per-request override) and client
     * (read from window.__CDN_BASE_URL__ injected into HTML by the server)
     * Empty string when no CDN is configured
     */
    cdnBaseURL?: string;
    /**
     * Domain information computed server-side from the request hostname.
     * Available during SSR (computed per-request) and SSG when a `hostname` option is
     * provided at build time. `null` when hostname is not known (SSG without hostname
     * configured, or pure SPA — no server to compute it via the public suffix list).
     */
    domainInfo?: DomainInfo | null;
    /**
     * Request context revision counter for reactivity
     * Format: `${timestamp}-${counter}` (e.g., "1729123456789-0", "1729123456789-1")
     * Increments whenever request context is modified to trigger re-renders
     * @internal
     */
    requestContextRevision?: string;
}
/**
 * React context for Unirend
 */
declare const UnirendContext: react.Context<UnirendContextValue>;
/**
 * Provider props
 */
interface UnirendProviderProps {
    children: ReactNode;
    value: UnirendContextValue;
}
/**
 * Request context management interface
 */
interface RequestContextManager {
    /**
     * Get a value from the request context
     * @param key - The key to retrieve
     * @returns The value associated with the key, or undefined if not found
     */
    get: (key: string) => unknown;
    /**
     * Set a value in the request context
     * @param key - The key to set
     * @param value - The value to associate with the key
     */
    set: (key: string, value: unknown) => void;
    /**
     * Check if a key exists in the request context
     * @param key - The key to check
     * @returns true if the key exists, false otherwise
     */
    has: (key: string) => boolean;
    /**
     * Delete a value from the request context
     * @param key - The key to delete
     * @returns true if the key existed and was deleted, false if it didn't exist
     */
    delete: (key: string) => boolean;
    /**
     * Clear all values from the request context
     * @returns The number of keys that were cleared
     */
    clear: () => number;
    /**
     * Get all keys from the request context
     * @returns An array of all keys
     */
    keys: () => string[];
    /**
     * Get the number of entries in the request context
     * @returns The number of key-value pairs
     */
    size: () => number;
}
/**
 * Helper to get the entire request context object
 * Works across SSR, SSG, and client environments
 */
declare function getRequestContextObject(context: UnirendContextValue): Record<string, unknown> | undefined;

/**
 * Collected head data built up during server-side renderToString.
 * Last write wins for title, meta and link entries accumulate.
 */
interface HeadCollector {
    title: string;
    metas: Array<Record<string, string>>;
    links: Array<Record<string, string>>;
}
/**
 * Context value is the collector on the server, null on the client.
 * null signals "render JSX tags so React 19 can hoist them to <head>".
 */
declare const UnirendHeadContext: react.Context<HeadCollector | null>;

export { type DomainInfo, type HeadCollector, type RequestContextManager, UnirendContext, type UnirendContextValue, UnirendHeadContext, type UnirendProviderProps, type UnirendRenderMode, getRequestContextObject, getRequestContextValue, hasSSGRequestContext, hasSSRRequestContext, hasWindowRequestContext, incrementContextRevision, setRequestContextValue };
