import React, { createContext, useContext, useState, useEffect } from 'react';
import { allPageData, SidebarItem, SidebarSubmenuItemData } from './data';
import { useLanguage } from '../../providers/language/LanguageContext';
import { resolveLanguageText, GenericPageData } from './pageInterface';
import { usePermissions } from '../../hooks/usePermissions';
import { FaHome, FaHatWizard, FaBriefcase, FaBuilding, FaProjectDiagram } from 'react-icons/fa';
import { RiFolderSettingsFill } from 'react-icons/ri';

// Configuration for parent groups that don't have a page definition
// Maps parentPath (can be nested like "start.real-estate") to icon and default order
const parentGroupConfig: Record<string, {
    icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
    defaultOrder?: number;
}> = {
    'start': {
        icon: FaHome,
        defaultOrder: 1
    },
    'workflows': {
        icon: FaProjectDiagram,
        defaultOrder: 2
    },
    'trustee': {
        icon: FaBriefcase,
        defaultOrder: 3
    },
    'basedata': {
        icon: RiFolderSettingsFill,
        defaultOrder: 4
    },
    'admin': {
        icon: FaHatWizard,
        defaultOrder: 5
    },
    'start.realestate': {
        icon: FaBuilding,
        defaultOrder: 2
    }
};

interface SidebarContextType {
    sidebarItems: SidebarItem[];
    loading: boolean;
    error: string | null;
    refreshSidebar: () => Promise<void>;
}

const SidebarContext = createContext<SidebarContextType | undefined>(undefined);

export const useSidebar = () => {
    const context = useContext(SidebarContext);
    if (!context) {
        throw new Error('useSidebar must be used within a SidebarProvider');
    }
    return context;
};

interface SidebarProviderProps {
    children: React.ReactNode;
}

export const SidebarProvider: React.FC<SidebarProviderProps> = ({ children }) => {
    const [sidebarItems, setSidebarItems] = useState<SidebarItem[]>([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);
    
    // Get translation function from language context
    const { t } = useLanguage();
    const { canView, preloadUiPermissions } = usePermissions();

    // Helper type for navigation tree nodes
    interface NavigationNode {
        id: string;
        pathSegment: string;
        fullPath: string; // Full dot-notation path (e.g., "start.real-estate")
        name: string;
        icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
        order: number;
        page?: GenericPageData; // If this node represents an actual page
        children: Map<string, NavigationNode>; // Keyed by path segment
        pages: GenericPageData[]; // Direct child pages
    }

    // Helper function to resolve node name
    const resolveNodeName = (pathSegment: string, _fullPath: string, page?: GenericPageData): string => {
        if (page) {
            return resolveLanguageText(page.name, t);
        }
        return pathSegment.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');
    };

    // Helper function to resolve node icon
    const resolveNodeIcon = (pathSegment: string, fullPath: string, page?: GenericPageData): React.ComponentType<React.SVGProps<SVGSVGElement>> | undefined => {
        if (page?.icon) {
            return page.icon;
        }
        // Check parentGroupConfig for nested paths first (e.g., "start.real-estate")
        if (parentGroupConfig[fullPath]?.icon) {
            return parentGroupConfig[fullPath].icon;
        }
        // Check parentGroupConfig for top-level segments (e.g., "start")
        if (fullPath === pathSegment && parentGroupConfig[pathSegment]?.icon) {
            return parentGroupConfig[pathSegment].icon;
        }
        return undefined;
    };

    // Helper function to resolve node order
    const resolveNodeOrder = (pathSegment: string, fullPath: string, page?: GenericPageData, childPages: GenericPageData[] = []): number => {
        if (page?.order !== undefined) {
            return page.order;
        }
        // Check parentGroupConfig for top-level segments
        if (fullPath === pathSegment && parentGroupConfig[pathSegment]?.defaultOrder !== undefined) {
            return parentGroupConfig[pathSegment].defaultOrder!;
        }
        // Use minimum order of child pages
        if (childPages.length > 0) {
            const childOrders = childPages.map(p => p.order ?? 0);
            return Math.min(...childOrders);
        }
        return 0;
    };

    // Build navigation tree from page data
    const buildNavigationTree = (): Map<string, NavigationNode> => {
        const rootNodes = new Map<string, NavigationNode>();

        // Process all pages with parent paths
        const pagesWithParents = allPageData.filter(
            page => page.parentPath && !page.hide && page.showInSidebar !== false
        );

        for (const page of pagesWithParents) {
            if (!page.parentPath) continue;

            // Parse parent path segments (e.g., "start.real-estate" -> ["start", "real-estate"])
            const pathSegments = page.parentPath.split('.');
            
            // Build path to root, creating nodes as needed
            let currentMap = rootNodes;
            let currentFullPath = '';
            
            for (let i = 0; i < pathSegments.length; i++) {
                const segment = pathSegments[i];
                currentFullPath = currentFullPath ? `${currentFullPath}.${segment}` : segment;
                
                // Get or create node for this segment
                if (!currentMap.has(segment)) {
                    // Check if there's a page for this path segment
                    const segmentPage = allPageData.find(
                        p => p.path === currentFullPath && !p.hide
                    );
                    
                    const node: NavigationNode = {
                        id: segmentPage?.id || currentFullPath,
                        pathSegment: segment,
                        fullPath: currentFullPath,
                        name: '', // Will be resolved later
                        icon: undefined, // Will be resolved later
                        order: 0, // Will be resolved later
                        page: segmentPage,
                        children: new Map(),
                        pages: []
                    };
                    
                    currentMap.set(segment, node);
                }
                
                const node = currentMap.get(segment)!;
                
                // If this is the last segment, add the page as a child page
                if (i === pathSegments.length - 1) {
                    node.pages.push(page);
                }
                
                // Move to next level
                currentMap = node.children;
            }
        }

        // Resolve names, icons, and orders for all nodes
        const resolveNode = (node: NavigationNode): void => {
            // Resolve children first (bottom-up)
            for (const childNode of node.children.values()) {
                resolveNode(childNode);
            }
            
            // Resolve this node
            node.name = resolveNodeName(node.pathSegment, node.fullPath, node.page);
            node.icon = resolveNodeIcon(node.pathSegment, node.fullPath, node.page);
            
            // Collect all child pages (from direct pages and nested children)
            const allChildPages = [...node.pages];
            for (const childNode of node.children.values()) {
                if (childNode.page) {
                    allChildPages.push(childNode.page);
                }
                allChildPages.push(...childNode.pages);
            }
            
            node.order = resolveNodeOrder(node.pathSegment, node.fullPath, node.page, allChildPages);
        };

        // Resolve all root nodes
        for (const node of rootNodes.values()) {
            resolveNode(node);
        }

        return rootNodes;
    };

    // Convert navigation tree node to sidebar submenu item (recursive)
    const nodeToSubmenuItem = async (node: NavigationNode, depth: number = 0): Promise<SidebarSubmenuItemData | null> => {
        // Filter child pages by RBAC and privilegeChecker
        const accessiblePages: GenericPageData[] = [];
        for (const page of node.pages) {
            try {
                const hasRBACAccess = await canView('UI', page.path);
                if (!hasRBACAccess) continue;
                
                if (page.privilegeChecker) {
                    try {
                        const hasPrivilege = await page.privilegeChecker();
                        if (!hasPrivilege) continue;
                    } catch (error) {
                        console.error(`Error checking privilegeChecker for page ${page.path}:`, error);
                        continue;
                    }
                }
                
                accessiblePages.push(page);
            } catch (error) {
                console.error(`Error checking RBAC access for page ${page.path}:`, error);
            }
        }

        // Process child nodes recursively (increment depth)
        const accessibleChildren: SidebarSubmenuItemData[] = [];
        for (const childNode of node.children.values()) {
            const childItem = await nodeToSubmenuItem(childNode, depth + 1);
            if (childItem) {
                accessibleChildren.push(childItem);
            }
        }

        // Combine pages and child nodes, assigning depth
        const allChildren: SidebarSubmenuItemData[] = [
            ...accessiblePages.map(page => ({
                id: page.id,
                name: resolveLanguageText(page.name, t),
                link: `/${page.path}`,
                icon: page.icon,
                depth: depth + 1 // Child pages are one level deeper
            })),
            ...accessibleChildren
        ];

        // If no accessible children, don't create this node
        if (allChildren.length === 0) {
            return null;
        }

        // If this node has a page itself, it shouldn't be a navigation node
        // But according to requirements: if it has subpages, it is NOT a page itself
        // So we create a navigation node without a link
        return {
            id: node.id,
            name: node.name,
            link: undefined, // Navigation node - not a clickable page
            icon: node.icon,
            submenu: allChildren.length > 0 ? allChildren : undefined,
            depth: depth // Current depth level
        };
    };

    // Convert navigation tree to sidebar items
    const treeToSidebarItems = async (tree: Map<string, NavigationNode>): Promise<SidebarItem[]> => {
        const items: SidebarItem[] = [];

        // Process each root node (depth 0 for top-level items)
        for (const node of tree.values()) {
            const submenuItem = await nodeToSubmenuItem(node, 0);
            if (submenuItem && submenuItem.submenu && submenuItem.submenu.length > 0) {
                items.push({
                    id: node.id,
                    name: node.name,
                    link: undefined, // Navigation node - not a clickable page
                    icon: node.icon,
                    moduleEnabled: true,
                    order: node.order,
                    submenu: submenuItem.submenu,
                    depth: 0 // Top-level items have depth 0
                });
            }
        }

        return items;
    };

    // Get sidebar items from page data
    const getSidebarItems = async (): Promise<SidebarItem[]> => {
        const items: SidebarItem[] = [];
        
        // Build navigation tree
        const navigationTree = buildNavigationTree();
        
        // Convert tree to sidebar items
        const treeItems = await treeToSidebarItems(navigationTree);
        items.push(...treeItems);
        
        // Get main pages (no parent path)
        const mainPages = allPageData
            .filter(page => !page.parentPath && !page.hide && page.showInSidebar !== false)
            .sort((a, b) => (a.order || 0) - (b.order || 0));
        
        // Process each main page
        for (const pageData of mainPages) {
            // Check RBAC permissions
            try {
                const hasRBACAccess = await canView('UI', pageData.path);
                if (!hasRBACAccess) {
                    continue;
                }
                
                // Check client-side privilegeChecker if provided
                if (pageData.privilegeChecker) {
                    try {
                        const hasPrivilege = await pageData.privilegeChecker();
                        if (!hasPrivilege) {
                            continue;
                        }
                    } catch (error) {
                        console.error(`Error checking privilegeChecker for ${pageData.path}:`, error);
                        continue;
                    }
                }
            } catch (error) {
                console.error(`Error checking RBAC access for ${pageData.path}:`, error);
                continue;
            }
            
            // Check if this page has subpages (legacy support)
            if (pageData.hasSubpages) {
                // Find all subpages for this parent
                const allSubpages = allPageData.filter(p => 
                    p.parentPath === pageData.path && 
                    !p.hide &&
                    p.showInSidebar !== false
                );
                        
                // Filter subpages by RBAC access
                const accessibleSubpages: GenericPageData[] = [];
                for (const subpage of allSubpages) {
                    try {
                        const hasSubpageRBACAccess = await canView('UI', subpage.path);
                        if (!hasSubpageRBACAccess) {
                            continue;
                        }
                        
                        if (subpage.privilegeChecker) {
                            try {
                                const hasPrivilege = await subpage.privilegeChecker();
                                if (!hasPrivilege) {
                                    continue;
                                }
                            } catch (error) {
                                console.error(`Error checking privilegeChecker for subpage ${subpage.path}:`, error);
                                continue;
                            }
                        }
                        
                        accessibleSubpages.push(subpage);
                    } catch (error) {
                        console.error(`Error checking RBAC access for subpage ${subpage.path}:`, error);
                    }
                }
                
                if (accessibleSubpages.length > 0) {
                    // Create item with submenu (no link since it has subpages)
                    items.push({
                        id: pageData.id,
                        name: resolveLanguageText(pageData.name, t),
                        link: undefined, // No link - has subpages, so it's a navigation node
                        icon: pageData.icon,
                        moduleEnabled: pageData.moduleEnabled ?? true,
                        order: pageData.order || 0,
                        depth: 0, // Top-level items have depth 0
                        submenu: accessibleSubpages.map(subpage => ({
                            id: subpage.id,
                            name: resolveLanguageText(subpage.name, t),
                            link: `/${subpage.path}`,
                            icon: subpage.icon,
                            depth: 1 // First level of submenu
                        }))
                    });
                } else {
                    // No accessible subpages, show as regular item
                    items.push({
                        id: pageData.id,
                        name: resolveLanguageText(pageData.name, t),
                        link: `/${pageData.path}`,
                        icon: pageData.icon,
                        moduleEnabled: pageData.moduleEnabled ?? true,
                        order: pageData.order || 0,
                        depth: 0 // Top-level items have depth 0
                    });
                }
            } else {
                // Regular items without subpages
                items.push({
                    id: pageData.id,
                    name: resolveLanguageText(pageData.name, t),
                    link: `/${pageData.path}`,
                    icon: pageData.icon,
                    moduleEnabled: pageData.moduleEnabled ?? true,
                    order: pageData.order || 0,
                    depth: 0 // Top-level items have depth 0
                });
            }
        }
        
        // Sort all items by order
        const sortedItems = items.sort((a, b) => (a.order || 0) - (b.order || 0));
        
        return sortedItems;
    };

    // Refresh sidebar items
    const refreshSidebar = async () => {
        console.log('🔄 SidebarProvider: Refreshing sidebar items...');
        setLoading(true);
        setError(null);
        
        try {
            // Preload all UI permissions in a single API call
            // This caches all permissions before iterating through pages
            await preloadUiPermissions();
            
            const items = await getSidebarItems();
            console.log('✅ SidebarProvider: Setting sidebar items:', {
                count: items.length,
                items: items.map(item => ({ id: item.id, link: item.link, name: item.name }))
            });
            setSidebarItems(items);
        } catch (err) {
            console.error('❌ SidebarProvider: Error refreshing sidebar:', err);
            setError(err instanceof Error ? err.message : t('Seitenleiste konnte nicht geladen werden'));
        } finally {
            setLoading(false);
        }
    };

    // Load sidebar items on mount and when language changes
    useEffect(() => {
        refreshSidebar();
    }, [t]);

    const contextValue: SidebarContextType = {
        sidebarItems,
        loading,
        error,
        refreshSidebar
    };

    return (
        <SidebarContext.Provider value={contextValue}>
            {children}
        </SidebarContext.Provider>
    );
};

export default SidebarProvider;
