'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// packages/ui/src/crud/components/EntityDisplayRenderer.tsx
/**
 * @fileoverview EntityDisplayRenderer component
 * @description High-level component that automatically fetches and displays entity data in read-only mode.
 * Perfect for detail/view pages - just pass the entity and it handles everything.
 *
 * @version 0.0.2
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
import { useEffect, useState, useMemo } from 'react';
import { Stack, Spinner } from '@donotdev/components';
import { useTranslation, isFieldVisible } from '@donotdev/core';
import { isCrudModuleAvailable, useCrud, DisplayFieldRenderer, } from '../crudImports';
import { useAuthSafe } from '../../utils/useAuthSafe';
/**
 * EntityDisplayRenderer - Automatically fetches and displays entity data
 *
 * Features:
 * - Automatic data fetching using useCrud
 * - Loading state handling
 * - Error handling
 * - Automatic field rendering (respects visibility rules)
 * - Full i18n support
 * - No form/submit buttons - pure read-only display
 *
 * @example
 * ```tsx
 * <EntityDisplayRenderer entity={carEntity} id={carId} />
 * ```
 */
export function EntityDisplayRenderer({ entity, id, t, className = '', loadingMessage, notFoundMessage, viewerRole: viewerRoleProp, excludeFields, }) {
    // Safe guard: isCrudModuleAvailable is a module-level constant (immutable after load).
    // eslint-disable-next-line react-hooks/rules-of-hooks
    if (!isCrudModuleAvailable)
        return null;
    // Auto-detect role from auth; prop overrides
    const authRole = useAuthSafe('userRole');
    const viewerRole = viewerRoleProp ?? authRole;
    const { get, loading, data: storeData, error: storeError, isAvailable, } = useCrud(entity);
    const [isFetching, setIsFetching] = useState(false);
    const [fetchError, setFetchError] = useState(null);
    const [data, setData] = useState(null);
    // Entity + crud namespaces so formatValue can resolve crud:price.* etc.
    const { t: tDual } = useTranslation([entity.namespace, 'crud']);
    const { t: tCrud } = useTranslation('crud');
    const translate = t || tDual;
    // Fetch data when id is available and service is ready
    useEffect(() => {
        // Early return if no ID
        if (!id) {
            setData(null);
            setFetchError(null);
            setIsFetching(false);
            return;
        }
        // Early return if service not ready
        if (!isAvailable || !get) {
            return;
        }
        let cancelled = false;
        setIsFetching(true);
        setFetchError(null);
        // Call get function - it should trigger the fetch
        get(id)
            .then((fetchedData) => {
            if (cancelled)
                return;
            setIsFetching(false);
            if (fetchedData) {
                setData(fetchedData);
                setFetchError(null);
            }
            else {
                setData(null);
                setFetchError(new Error('Entity not found'));
            }
        })
            .catch((err) => {
            if (cancelled)
                return;
            setIsFetching(false);
            setFetchError(err instanceof Error ? err : new Error(String(err)));
            setData(null);
        });
        return () => {
            cancelled = true;
        };
    }, [id, get, isAvailable]);
    // Priority: store data (reactive, updated by other components) > local fetch data.
    // Store may already have the entity from a list view or prior navigation,
    // so we prefer it to avoid a redundant fetch. Local fetch is the fallback
    // when the entity isn't in the store yet (e.g., direct URL access).
    const displayData = storeData || data;
    const displayError = storeError || fetchError;
    const isLoading = loading || isFetching || !id;
    // Filter fields: respect visibility AND skip empty values
    // MUST be called before any early returns (Rules of Hooks)
    const visibleFields = useMemo(() => {
        if (!displayData)
            return [];
        return Object.entries(entity.fields).filter(([fieldName, fieldConfig]) => {
            // Skip excluded fields
            if (excludeFields?.includes(fieldName)) {
                return false;
            }
            // Check visibility first
            if (!isFieldVisible(fieldConfig.visibility, viewerRole)) {
                return false;
            }
            // Skip hidden fields
            if (fieldConfig.visibility === 'hidden') {
                return false;
            }
            // Get field value
            const value = displayData[fieldName];
            // Hide if value is empty/null/undefined
            if (value === null || value === undefined) {
                return false;
            }
            // Hide empty strings
            if (typeof value === 'string' && value.trim() === '') {
                return false;
            }
            // Hide empty arrays
            if (Array.isArray(value) && value.length === 0) {
                return false;
            }
            // Hide empty objects (but allow objects with properties)
            if (typeof value === 'object' &&
                !Array.isArray(value) &&
                value !== null &&
                Object.keys(value).length === 0) {
                return false;
            }
            return true;
        });
    }, [entity.fields, viewerRole, displayData, excludeFields]);
    // Loading state
    if (isLoading) {
        return (_jsx("div", { style: {
                position: 'relative',
                width: '100%',
                gridColumn: '1 / -1',
                display: 'contents',
            }, className: className, children: _jsx(Spinner, { overlay: true, "aria-label": loadingMessage ||
                    tCrud('form.loading', { defaultValue: 'Loading...' }) }) }));
    }
    // Error or not found state
    if (displayError || !displayData) {
        return (_jsx(Stack, { align: "center", justify: "center", style: {
                padding: 'var(--gap-3xl)',
                textAlign: 'center',
            }, className: className, children: _jsxs(Stack, { direction: "column", gap: "tight", children: [_jsx("h3", { style: { color: 'var(--muted-foreground)' }, children: notFoundMessage ||
                            tCrud('errors.notFound', {
                                defaultValue: `${entity.name} not found`,
                            }) }), displayError && (_jsx("p", { style: {
                            color: 'var(--destructive)',
                            fontSize: 'var(--font-size-sm)',
                        }, children: displayError instanceof Error
                            ? displayError.message
                            : String(displayError) }))] }) }));
    }
    // Render all visible fields with values
    return (_jsx(Stack, { direction: "column", className: className, children: visibleFields.map(([fieldName, fieldConfig]) => {
            return (_jsx(DisplayFieldRenderer, { name: fieldName, config: fieldConfig, value: displayData[fieldName], t: translate }, fieldName));
        }) }));
}
export default EntityDisplayRenderer;
