'use client';
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// packages/ui/src/internal/layout/DnDevLayout.tsx
/**
 * @fileoverview DnDevLayout Component
 * @description Layout orchestrator using zone components.
 * Handles CSS grid setup, data attributes, and zone rendering.
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
import { useLayoutEffect, useEffect, useRef, useMemo, Suspense, startTransition, lazy, } from 'react';
import { cn, Stack } from '@donotdev/components';
import { isClient, isNextJs, isDev, useBreakpoint } from '@donotdev/core';
import { useLayout } from '@donotdev/core';
import { useTranslation } from '@donotdev/core';
import { useAppConfig } from '@donotdev/core';
import { LAYOUT_PRESET, DENSITY } from '@donotdev/core';
import { useLocation } from '@donotdev/ui/routing/hooks';
import Breadcrumbs from '../../components/layout/components/Breadcrumbs';
import { GoToWrapper } from '../../routing';
import { DEFAULT_SLOTS } from './config/defaults';
import { presetRegistry } from './config/presets';
import { DnDevHeader, DnDevSidebar, DnDevFooter, DnDevMergedBar, } from './zones';
const DebugTools = lazy(() => {
    return import('../devtools')
        .then((m) => {
        return { default: m.DebugTools };
    })
        .catch(() => {
        return { default: () => _jsx(_Fragment, {}) };
    });
});
/**
 * Layout preset to density mapping
 */
const LAYOUT_DENSITY_DEFAULTS = {
    [LAYOUT_PRESET.ADMIN]: DENSITY.COMPACT,
    [LAYOUT_PRESET.MOOLTI]: DENSITY.COMPACT,
    [LAYOUT_PRESET.LANDING]: DENSITY.EXPRESSIVE,
    [LAYOUT_PRESET.GAME]: DENSITY.EXPRESSIVE,
    [LAYOUT_PRESET.DOCS]: DENSITY.STANDARD,
    [LAYOUT_PRESET.BLOG]: DENSITY.STANDARD,
    [LAYOUT_PRESET.PLAIN]: DENSITY.STANDARD,
};
/**
 * DnDevLayout - Layout orchestrator with zone components
 *
 * Renders CSS grid zones using dedicated zone components.
 * Handles data attributes and CSS variable overrides.
 * MergedBar is always rendered - CSS controls visibility.
 *
 * Layout preset is always read from the store via useLayout('layoutPreset').
 * The store is initialized from appConfig.preset and can be changed at runtime
 * via useLayout('setLayoutPreset').
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export const DnDevLayout = ({ children, layout, className, }) => {
    // Store is single source of truth for preset
    const preset = useLayout('layoutPreset');
    const routePresetOverride = useLayout('routePresetOverride');
    const isMobile = useBreakpoint('isMobileOrTablet');
    const { app, features } = useAppConfig();
    const debugEnabled = isDev() && features?.debug === true;
    // Subscribe to language changes for zone re-renders
    useTranslation('dndev');
    // Layout config props
    const breadcrumbs = layout?.breadcrumbs ?? 'smart';
    const footerMode = layout?.footerMode;
    const footerInline = footerMode === 'scroll' || isMobile;
    // Route detection for animations
    const location = useLocation();
    const pathname = location.pathname;
    const mainRef = useRef(null);
    // Platform content handling
    const content = children;
    // Effective preset: route override > app default > fallback
    const effectivePreset = useMemo(() => {
        return routePresetOverride || preset || 'landing';
    }, [routePresetOverride, preset]);
    // Get preset config (presets only override what's different, defaults fill the rest)
    const config = useMemo(() => {
        const presetConfig = (presetRegistry[effectivePreset] ??
            presetRegistry.landing);
        return {
            name: presetConfig.name,
            header: presetConfig.header,
            sidebar: presetConfig.sidebar,
            footer: presetConfig.footer,
            mobile: presetConfig.mobile,
        };
    }, [effectivePreset]);
    // Resolve header with consumer overrides
    const resolvedHeader = useMemo(() => {
        if (typeof layout?.header === 'function') {
            return _jsx(layout.header, {});
        }
        // Determine effective header config (mobile overrides desktop when on mobile)
        const effectiveHeader = isMobile
            ? layout?.mobile?.header ||
                config.mobile?.header ||
                layout?.header ||
                config.header
            : layout?.header || config.header;
        if (effectiveHeader && typeof effectiveHeader === 'object') {
            // Priority: consumer mobile > preset mobile > consumer desktop > preset desktop > defaults
            const startSlot = isMobile && layout?.mobile?.header?.start !== undefined
                ? layout.mobile.header.start
                : isMobile && config.mobile?.header?.start !== undefined
                    ? config.mobile.header.start
                    : layout?.header &&
                        typeof layout.header === 'object' &&
                        layout.header.start !== undefined
                        ? layout.header.start
                        : (config.header?.start ?? DEFAULT_SLOTS.header.start);
            const centerSlot = isMobile && layout?.mobile?.header?.center !== undefined
                ? layout.mobile.header.center
                : isMobile && config.mobile?.header?.center !== undefined
                    ? config.mobile.header.center
                    : layout?.header &&
                        typeof layout.header === 'object' &&
                        layout.header.center !== undefined
                        ? layout.header.center
                        : (config.header?.center ?? DEFAULT_SLOTS.header.center);
            const endSlot = isMobile && layout?.mobile?.header?.end !== undefined
                ? layout.mobile.header.end
                : isMobile && config.mobile?.header?.end !== undefined
                    ? config.mobile.header.end
                    : layout?.header &&
                        typeof layout.header === 'object' &&
                        layout.header.end !== undefined
                        ? layout.header.end
                        : (config.header?.end ?? DEFAULT_SLOTS.header.end);
            return (_jsx(DnDevHeader, { start: startSlot(), center: centerSlot(), end: endSlot() }));
        }
        // No consumer override - use preset or defaults
        const effectiveStartSlot = isMobile
            ? (config.mobile?.header?.start ??
                config.header?.start ??
                DEFAULT_SLOTS.header.start)
            : (config.header?.start ?? DEFAULT_SLOTS.header.start);
        const effectiveCenterSlot = isMobile
            ? (config.mobile?.header?.center ??
                config.header?.center ??
                DEFAULT_SLOTS.header.center)
            : (config.header?.center ?? DEFAULT_SLOTS.header.center);
        const effectiveEndSlot = isMobile
            ? (config.mobile?.header?.end ??
                config.header?.end ??
                DEFAULT_SLOTS.header.end)
            : (config.header?.end ?? DEFAULT_SLOTS.header.end);
        return (_jsx(DnDevHeader, { start: effectiveStartSlot(), center: effectiveCenterSlot(), end: effectiveEndSlot() }));
    }, [layout?.header, layout?.mobile?.header, config, isMobile]);
    // Resolve sidebar with consumer overrides
    const resolvedSidebar = useMemo(() => {
        if (typeof layout?.sidebar === 'function') {
            return _jsx(layout.sidebar, {});
        }
        if (layout?.sidebar && typeof layout.sidebar === 'object') {
            // If consumer provides a function (including () => null), use it; otherwise fall back
            const topSlot = layout.sidebar.top !== undefined
                ? layout.sidebar.top
                : (config.sidebar?.top ?? DEFAULT_SLOTS.sidebar.top);
            const contentSlot = layout.sidebar.content !== undefined
                ? layout.sidebar.content
                : (config.sidebar?.content ?? DEFAULT_SLOTS.sidebar.content);
            const bottomSlot = layout.sidebar.bottom !== undefined
                ? layout.sidebar.bottom
                : (config.sidebar?.bottom ?? DEFAULT_SLOTS.sidebar.bottom);
            return (_jsx(DnDevSidebar, { top: topSlot(), content: contentSlot(), bottom: bottomSlot(), defaultWidth: config.sidebar?.defaultWidth ?? DEFAULT_SLOTS.sidebar.defaultWidth, minWidth: config.sidebar?.minWidth ?? DEFAULT_SLOTS.sidebar.minWidth, maxWidth: config.sidebar?.maxWidth ?? DEFAULT_SLOTS.sidebar.maxWidth }));
        }
        // No consumer override - use preset or defaults
        const topSlot = config.sidebar?.top ?? DEFAULT_SLOTS.sidebar.top;
        const contentSlot = config.sidebar?.content ?? DEFAULT_SLOTS.sidebar.content;
        const bottomSlot = config.sidebar?.bottom ?? DEFAULT_SLOTS.sidebar.bottom;
        return (_jsx(DnDevSidebar, { top: topSlot(), content: contentSlot(), bottom: bottomSlot(), defaultWidth: config.sidebar?.defaultWidth ?? DEFAULT_SLOTS.sidebar.defaultWidth, minWidth: config.sidebar?.minWidth ?? DEFAULT_SLOTS.sidebar.minWidth, maxWidth: config.sidebar?.maxWidth ?? DEFAULT_SLOTS.sidebar.maxWidth }));
    }, [layout?.sidebar, config.sidebar]);
    // Resolve footer with consumer overrides
    const resolvedFooter = useMemo(() => {
        if (layout?.footer) {
            return _jsx(layout.footer, {});
        }
        return _jsx(DnDevFooter, { app: app });
    }, [layout?.footer, app]);
    // Resolve mergedbar with consumer overrides
    const resolvedMergedBar = useMemo(() => {
        if (!config.mobile?.mergedBar)
            return null;
        if (typeof layout?.mergedbar === 'function') {
            return _jsx(layout.mergedbar, {});
        }
        const mergedBarConfig = config.mobile.mergedBar;
        if (layout?.mergedbar && typeof layout.mergedbar === 'object') {
            // If consumer provides a function (including () => null), use it; otherwise fall back
            const triggerSlot = layout.mergedbar.trigger !== undefined
                ? layout.mergedbar.trigger
                : (mergedBarConfig.trigger ??
                    config.header?.start ??
                    DEFAULT_SLOTS.header.start);
            const topSlot = layout.mergedbar.top !== undefined
                ? layout.mergedbar.top
                : (mergedBarConfig.top ?? DEFAULT_SLOTS.mobile.mergedBar.top);
            const contentSlot = layout.mergedbar.content !== undefined
                ? layout.mergedbar.content
                : (mergedBarConfig.content ??
                    config.sidebar?.content ??
                    DEFAULT_SLOTS.sidebar.content);
            const bottomSlot = layout.mergedbar.bottom !== undefined
                ? layout.mergedbar.bottom
                : (mergedBarConfig.bottom ??
                    config.sidebar?.bottom ??
                    DEFAULT_SLOTS.sidebar.bottom);
            return (_jsx(DnDevMergedBar, { position: mergedBarConfig.position, height: mergedBarConfig.height, trigger: triggerSlot(), top: topSlot(), content: contentSlot(), bottom: bottomSlot() }));
        }
        // No consumer override - use preset or defaults
        const triggerSlot = mergedBarConfig.trigger ??
            config.header?.start ??
            DEFAULT_SLOTS.header.start;
        const topSlot = mergedBarConfig.top ?? DEFAULT_SLOTS.mobile.mergedBar.top;
        const contentSlot = mergedBarConfig.content ??
            config.sidebar?.content ??
            DEFAULT_SLOTS.sidebar.content;
        const bottomSlot = mergedBarConfig.bottom ??
            config.sidebar?.bottom ??
            DEFAULT_SLOTS.sidebar.bottom;
        return (_jsx(DnDevMergedBar, { position: mergedBarConfig.position, height: mergedBarConfig.height, trigger: triggerSlot(), top: topSlot(), content: contentSlot(), bottom: bottomSlot() }));
    }, [layout?.mergedbar, config]);
    // Apply routing animation data attribute (useLayoutEffect = before paint)
    useLayoutEffect(() => {
        if (!isClient() || !mainRef.current)
            return;
        const routingAnimation = getComputedStyle(document.documentElement)
            .getPropertyValue('--routing-animation')
            .trim() || 'none';
        mainRef.current.setAttribute('data-routing-animation', routingAnimation);
    }, [pathname]);
    // Apply data attributes
    useLayoutEffect(() => {
        if (!isClient() || !effectivePreset)
            return;
        const updateDOM = () => {
            const root = document.documentElement;
            root.setAttribute('data-layout', effectivePreset);
            const density = LAYOUT_DENSITY_DEFAULTS[effectivePreset] || DENSITY.STANDARD;
            root.setAttribute('data-density', density);
        };
        startTransition(updateDOM);
    }, [effectivePreset]);
    return (_jsxs("div", { className: cn('dndev-layout', className), "data-footer-inline": footerInline || undefined, children: [resolvedHeader, resolvedSidebar, _jsxs("main", { ref: mainRef, role: "main", className: "main", children: [breadcrumbs !== 'never' && (_jsx("div", { className: "breadcrumbs-container", children: _jsx(Breadcrumbs, { variant: breadcrumbs === 'always' ? 'default' : 'smart' }) })), debugEnabled && (_jsx(Suspense, { fallback: null, children: _jsx(DebugTools, {}) })), layout?.wrapper ? layout.wrapper({ children: content }) : content, footerInline && resolvedFooter] }), !footerInline && resolvedFooter, resolvedMergedBar, _jsx(GoToWrapper, {})] }));
};
