'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState } from 'react';
import { ReactFlow, Background, BackgroundVariant, Panel } from '@xyflow/react';
import { Plus } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { cn } from '../../../lib/utils.js';
import { Button } from '../../ui/button.js';
import { EmptyState } from '../../common/empty-state/index.js';
import { FeatureNode } from '../../common/feature-node/index.js';
import { RepositoryNode } from '../../common/repository-node/index.js';
import { ApplicationNode } from '../../common/application-node/application-node.js';
import { DependencyEdge } from './dependency-edge.js';
const FALLBACK_VIEWPORT = { x: 30, y: 30, zoom: 0.85 };
export function FeaturesCanvas({ nodes, edges, selectedFeatureId, selectedRepository, defaultViewport, onNodesChange, onAddFeature, onConnect, onNodeClick, onPaneClick, onCanvasDrag, onMoveEnd, toolbar, showToolbarOnEmpty = true, emptyState, }) {
    const { t } = useTranslation('web');
    const nodeTypes = useMemo(() => ({
        featureNode: FeatureNode,
        repositoryNode: RepositoryNode,
        applicationNode: ApplicationNode,
    }), []);
    const edgeTypes = useMemo(() => ({
        dependencyEdge: DependencyEdge,
    }), []);
    // Callbacks and showHandles are already injected into node.data by deriveGraph.
    // Apply selectedFeatureId and selectedRepository highlighting here.
    const enrichedNodes = useMemo(() => {
        const hasFeatureSel = selectedFeatureId != null;
        const hasRepoSel = selectedRepository != null &&
            (selectedRepository.id != null || selectedRepository.path != null);
        if (!hasFeatureSel && !hasRepoSel)
            return nodes;
        return nodes.map((node) => {
            if (hasFeatureSel &&
                node.type === 'featureNode' &&
                node.data.featureId === selectedFeatureId) {
                return { ...node, selected: true };
            }
            if (hasRepoSel && node.type === 'repositoryNode') {
                const rd = node.data;
                const matchById = selectedRepository.id != null &&
                    (node.id === selectedRepository.id || rd.id === selectedRepository.id);
                const matchByPath = selectedRepository.path != null && rd.repositoryPath === selectedRepository.path;
                if (matchById || matchByPath)
                    return { ...node, selected: true };
            }
            return node;
        });
    }, [nodes, selectedFeatureId, selectedRepository]);
    const isEmpty = nodes.length === 0;
    // Track empty→populated transition for exit animation.
    // When isEmpty flips from true to false, keep the overlay mounted
    // and fade it out before removing it from the DOM.
    const [showOverlay, setShowOverlay] = useState(isEmpty);
    const [overlayExiting, setOverlayExiting] = useState(false);
    const prevEmptyRef = useRef(isEmpty);
    useEffect(() => {
        if (prevEmptyRef.current && !isEmpty) {
            // Was empty, now populated — start exit animation
            setOverlayExiting(true);
            const timer = setTimeout(() => {
                setShowOverlay(false);
                setOverlayExiting(false);
            }, 300);
            prevEmptyRef.current = isEmpty;
            return () => clearTimeout(timer);
        }
        if (!prevEmptyRef.current && isEmpty) {
            // Was populated, now empty — show overlay immediately
            setShowOverlay(true);
        }
        prevEmptyRef.current = isEmpty;
    }, [isEmpty]);
    const fallbackEmptyState = isEmpty && !emptyState ? (_jsx(EmptyState, { title: t('canvas.noFeatures'), description: t('canvas.noFeaturesDescription'), action: _jsxs(Button, { onClick: onAddFeature, children: [_jsx(Plus, { className: "me-2 h-4 w-4" }), t('canvas.newFeature')] }) })) : null;
    const overlayContent = emptyState ?? fallbackEmptyState;
    return (_jsxs("div", { "data-testid": isEmpty ? 'features-canvas-empty' : 'features-canvas', "data-no-drawer-close": true, className: "dark:bg-background pointer-events-auto relative h-full w-full bg-[#f6f7f8]", children: [_jsxs(ReactFlow, { nodes: enrichedNodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onConnect: onConnect, onNodesChange: onNodesChange, onNodeClick: onNodeClick, onPaneClick: onPaneClick, onMoveStart: onCanvasDrag, onMoveEnd: onMoveEnd, defaultViewport: defaultViewport ?? FALLBACK_VIEWPORT, nodesDraggable: false, nodesConnectable: false, elementsSelectable: false, proOptions: { hideAttribution: true }, className: "[&_.react-flow__pane]:!cursor-default", children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 24, size: 1, color: "#b8bcc4", className: "dark:[&_circle]:!fill-white/[0.1]" }), toolbar && !isEmpty ? (_jsx(Panel, { position: "top-right", className: "!me-3 !mt-3", children: toolbar })) : null] }), showOverlay && overlayContent ? (_jsx("div", { className: cn('pointer-events-none absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300', overlayExiting ? 'opacity-0' : 'animate-in fade-in opacity-100 duration-200'), children: _jsx("div", { className: "pointer-events-auto h-full w-full", children: overlayContent }) })) : null, toolbar && isEmpty && showToolbarOnEmpty ? (_jsx("div", { className: "pointer-events-auto absolute end-3 top-3 z-20", children: toolbar })) : null] }));
}
