import React, { Suspense, useMemo } from 'react';
import { Routes, Route, Link, Navigate, matchPath, useLocation } from 'react-router-dom';
import { SetupRegistry, SetupPageDefinition } from '../../registries/SetupRegistry';
import { ComponentRegistry } from '../../registries/ComponentRegistry';
import { Settings as SettingsIcon, AlertCircle } from 'lucide-react';
import * as LucideIcons from 'lucide-react';
import { useSystemPermission } from '@nexuscrm/host-sdk';
import {
    DEFAULT_SETUP_PERMISSION,
    SetupSystemPermission,
    getSetupPageRequiredPermission,
} from '../../core/navigation/setupPermissions';
import {
    buildSetupPageChildPath,
    buildSetupPageChildRoutePath,
    getSetupPageRelativePath,
    tryGetSetupBasePath,
    tryGetSetupPagePath,
} from '../../core/navigation/setupPagePaths';
import {
    getSetupPageChildRoutes,
    type SetupPageChildRouteDefinition,
} from '@nexuscrm/host-sdk';
import { useApp } from '@nexuscrm/host-sdk';

// ============================================================================
// Shared Hook - Single source of truth for loading Setup pages
// ============================================================================

function useSetupPages(appId: string | null) {
    const [pages, setPages] = React.useState<SetupPageDefinition[]>(
        SetupRegistry.isLoaded() ? SetupRegistry.getPages(appId) : []
    );
    const [loading, setLoading] = React.useState(!SetupRegistry.isLoaded());

    React.useEffect(() => {
        if (SetupRegistry.isLoaded()) {
            setPages(SetupRegistry.getPages(appId));
            return;
        }

        const load = async () => {
            await SetupRegistry.loadFromDatabase();
            setPages(SetupRegistry.getPages(appId));
            setLoading(false);
        };
        load();
    }, [appId]);

    return { pages, loading };
}

// ============================================================================
// Category Colors - Could be metadata-driven in future
// ============================================================================

const CATEGORY_COLORS: Record<string, { bg: string; text: string; hover: string }> = {
    'Security': { bg: 'bg-emerald-100', text: 'text-emerald-600', hover: 'group-hover:bg-emerald-600' },
    'Automation': { bg: 'bg-purple-100', text: 'text-purple-600', hover: 'group-hover:bg-purple-600' },
    'System': { bg: 'bg-cyan-100', text: 'text-cyan-600', hover: 'group-hover:bg-cyan-600' },
    'Objects': { bg: 'bg-amber-100', text: 'text-amber-600', hover: 'group-hover:bg-amber-600' },
};
const DEFAULT_COLORS = { bg: 'bg-blue-100', text: 'text-blue-600', hover: 'group-hover:bg-blue-600' };

function setupChildRouteKey(route: SetupPageChildRouteDefinition): string {
    return `${route.pageId}:${route.childRoutePath}`;
}

interface SetupBreadcrumbSegment {
    label: string;
    to?: string;
}

function expandChildPathTemplate(template: string, params: Record<string, string | undefined>): string {
    return template.replace(/\{([^}]+)\}/g, (_, name: string) => params[name] ?? '');
}

function setupChildRoutePattern(
    route: SetupPageChildRouteDefinition,
    appId: string | null | undefined,
): string | undefined {
    const parentPath = tryGetSetupPagePath(route.pageId, appId);
    if (!parentPath) return undefined;
    const childRoutePath = route.childRoutePath.replace(/^\/+/, '');
    return `${parentPath.replace(/\/$/, '')}/${childRoutePath}`;
}

function matchSetupChildRoute(
    appId: string | null | undefined,
    routes: readonly SetupPageChildRouteDefinition[],
    pathname: string,
) {
    const candidates = [...routes].sort((a, b) => b.childRoutePath.length - a.childRoutePath.length);
    for (const route of candidates) {
        const pattern = setupChildRoutePattern(route, appId);
        if (!pattern) continue;
        const match = matchPath({ path: pattern, end: true }, pathname);
        if (match) {
            return { route, match };
        }
    }
    return undefined;
}

// ============================================================================
// Not Implemented Placeholder Component
// ============================================================================

const NotImplemented: React.FC<{ componentName: string; pageLabel: string }> = ({ componentName, pageLabel }) => (
    <div className="flex flex-col items-center justify-center p-12 bg-slate-50 rounded-xl border-2 border-dashed border-slate-300">
        <AlertCircle className="w-16 h-16 text-slate-400 mb-4" />
        <h2 className="text-xl font-semibold text-slate-700 mb-2">{pageLabel}</h2>
        <p className="text-slate-500 text-center max-w-md">
            This feature is coming soon. The <code className="bg-slate-200 px-2 py-1 rounded text-sm">{componentName}</code> component is registered in metadata but not yet implemented.
        </p>
    </div>
);

function useSetupPermissions(): Record<SetupSystemPermission, boolean> {
    const viewSetup = useSystemPermission('ViewSetup');
    const manageUsers = useSystemPermission('ManageUsers');
    const manageProfilesPermSets = useSystemPermission('ManageProfilesPermSets');
    const manageRoles = useSystemPermission('ManageRoles');
    const manageSharing = useSystemPermission('ManageSharing');

    return useMemo(() => ({
        ViewSetup: viewSetup,
        ManageUsers: manageUsers,
        ManageProfilesPermSets: manageProfilesPermSets,
        ManageRoles: manageRoles,
        ManageSharing: manageSharing,
    }), [manageProfilesPermSets, manageRoles, manageSharing, manageUsers, viewSetup]);
}

function useCanAccessSetupPage(): (page: SetupPageDefinition) => boolean {
    const permissions = useSetupPermissions();

    return React.useCallback((page: SetupPageDefinition) => {
        const requiredPermission = page.permissionRequired ?? getSetupPageRequiredPermission(page.path);
        if (!requiredPermission) {
            return true;
        }

        return permissions[requiredPermission] ?? false;
    }, [permissions]);
}

const SetupPagePermissionGate: React.FC<{
    appId: string | null;
    requiredPermission?: SetupSystemPermission;
    children: React.ReactNode;
}> = ({ appId, requiredPermission, children }) => {
    const permissions = useSetupPermissions();
    const permissionToCheck = requiredPermission ?? DEFAULT_SETUP_PERMISSION;

    if (!permissions[permissionToCheck]) {
        return <Navigate to={permissions.ViewSetup ? tryGetSetupBasePath(appId) ?? '/' : '/'} replace />;
    }

    return <>{children}</>;
};

// ============================================================================
// Setup Home - Displays tiles from SetupRegistry
// ============================================================================

const SetupHome: React.FC<{ appId: string | null }> = ({ appId }) => {
    const { pages, loading } = useSetupPages(appId);
    const canAccessPage = useCanAccessSetupPage();

    const visiblePages = useMemo(() => pages.filter(canAccessPage), [canAccessPage, pages]);

    // Group pages by category
    const categories = useMemo(() => {
        return visiblePages.reduce((acc, page) => {
            const cat = page.category || 'Other';
            if (!acc[cat]) acc[cat] = [];
            acc[cat].push(page);
            return acc;
        }, {} as Record<string, SetupPageDefinition[]>);
    }, [visiblePages]);

    if (loading) {
        return (
            <div className="flex items-center justify-center p-12">
                <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
            </div>
        );
    }

    return (
        <div className="space-y-8">
            {Object.entries(categories).map(([category, categoryPages]) => (
                <div key={category}>
                    <h2 className="text-lg font-semibold text-slate-700 mb-4">{category}</h2>
                    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                        {categoryPages.map((page) => {
                            const IconComponent = (LucideIcons as unknown as Record<string, React.FC<{ size?: number }>>)[page.icon] || LucideIcons.Box;
                            const colors = CATEGORY_COLORS[page.category || ''] || DEFAULT_COLORS;
                            const isImplemented = ComponentRegistry.has(page.component_name);

                            return (
                                <Link
                                    key={page.id}
                                    to={page.path || '#'}
                                    className={`p-6 bg-white/80 backdrop-blur-xl rounded-2xl border border-white/20 hover:border-blue-500 hover:shadow-xl transition-all group ${!isImplemented ? 'opacity-75' : ''}`}
                                >
                                    <div className={`w-10 h-10 ${colors.bg} rounded-lg flex items-center justify-center ${colors.text} mb-4 ${colors.hover} group-hover:text-white transition-colors`}>
                                        <IconComponent size={20} />
                                    </div>
                                    <div className="flex items-center gap-2 mb-2">
                                        <h3 className="text-lg font-semibold text-slate-800">{page.label}</h3>
                                        {!isImplemented && (
                                            <span className="text-xs bg-slate-200 text-slate-600 px-2 py-0.5 rounded">Coming Soon</span>
                                        )}
                                    </div>
                                    <p className="text-slate-500 text-sm">{page.description}</p>
                                </Link>
                            );
                        })}
                    </div>
                </div>
            ))}
        </div>
    );
};

// ============================================================================
// Dynamic Route Generator - Creates routes from metadata
// Uses ComponentRegistry as single source of truth for component resolution
// ============================================================================

const DynamicSetupRoutes: React.FC<{ appId: string | null }> = ({ appId }) => {
    const { pages, loading } = useSetupPages(appId);

    if (loading) {
        return (
            <div className="flex items-center justify-center p-12">
                <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
            </div>
        );
    }

    const childRoutes = getSetupPageChildRoutes(appId);

    return (
        <Routes>
            <Route path="/" element={<SetupHome appId={appId} />} />

            {/* Dynamic routes from metadata */}
            {pages.map((page) => {
                const safeComponentName = page.component_name || '';
                const relativePath = getSetupPageRelativePath(page.path, safeComponentName, appId);

                const Component = ComponentRegistry.get(page.component_name);
                const requiredPermission = page.permissionRequired ?? getSetupPageRequiredPermission(page.path, appId);

                return (
                    <Route
                        key={page.id}
                        path={relativePath}
                        element={
                            <SetupPagePermissionGate appId={appId} requiredPermission={requiredPermission}>
                                {Component
                                    ? <Suspense fallback={<div className="flex items-center justify-center p-12"><div className="w-6 h-6 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" /></div>}><Component /></Suspense>
                                    : <NotImplemented componentName={page.component_name} pageLabel={page.label} />}
                            </SetupPagePermissionGate>
                        }
                    />
                );
            })}

            {/* App-owned child routes are registered by the app frontend adapter. */}
            {childRoutes.map((route) => {
                const path = buildSetupPageChildRoutePath(route.pageId, route.childRoutePath, appId);
                return (
                    <Route
                        key={setupChildRouteKey(route)}
                        path={path}
                        element={
                            <SetupPagePermissionGate
                                appId={appId}
                                requiredPermission={(route.requiredPermission as SetupSystemPermission | undefined) ?? DEFAULT_SETUP_PERMISSION}
                            >
                                <SetupChildRouteElement route={route} />
                            </SetupPagePermissionGate>
                        }
                    />
                );
            })}

            {/* Dynamic routes from SetupRegistry handle all setup page paths */}

            {/* Catch-all for unknown routes */}
            <Route path="*" element={
                <div className="text-center p-12 text-slate-500">
                    <AlertCircle className="w-12 h-12 mx-auto mb-4 text-slate-400" />
                    <p>Page not found in Setup. <Link to={tryGetSetupBasePath(appId) ?? '/'} className="text-blue-600 hover:underline">Go back to Setup</Link></p>
                </div>
            } />
        </Routes>
    );
};

// Wrapper components for nested routes to use ComponentRegistry
const LazyFallback = <div className="flex items-center justify-center p-12"><div className="w-6 h-6 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" /></div>;

const SetupChildRouteElement: React.FC<{ route: SetupPageChildRouteDefinition }> = ({ route }) => {
    const Component = ComponentRegistry.get(route.componentName);
    return Component
        ? <Suspense fallback={LazyFallback}><Component /></Suspense>
        : <NotImplemented componentName={route.componentName} pageLabel={route.pageLabel ?? route.componentName} />;
};


// ============================================================================
// Main Setup Component
// ============================================================================

export const Setup: React.FC = () => {
    const location = useLocation();
    const { currentFrontendAppId, loading: appsLoading } = useApp();
    const setupBasePath = tryGetSetupBasePath(currentFrontendAppId);
    const isHome = Boolean(setupBasePath && location.pathname === setupBasePath);
    const setupChildRoutes = useMemo(
        () => getSetupPageChildRoutes(currentFrontendAppId),
        [currentFrontendAppId],
    );
    const matchedChildRoute = useMemo(
        () => matchSetupChildRoute(currentFrontendAppId, setupChildRoutes, location.pathname),
        [currentFrontendAppId, location.pathname, setupChildRoutes],
    );

    // Detect detail sub-pages that render their own header
    const isDetailSubPage = Boolean(matchedChildRoute && matchedChildRoute.route.rendersOwnHeader !== false);

    const childBreadcrumbSegments = useMemo<SetupBreadcrumbSegment[]>(() => {
        const route = matchedChildRoute?.route;
        const breadcrumbs = route?.breadcrumbs;
        if (!route || !breadcrumbs?.length) return [];

        const parentPage = SetupRegistry.getPage(route.pageId, currentFrontendAppId);
        const params = matchedChildRoute.match.params;
        return breadcrumbs.flatMap((segment) => {
            if (segment.type === 'parentPage') {
                return parentPage ? [{ label: parentPage.label, to: parentPage.path }] : [];
            }
            if (segment.type === 'routeParam') {
                const label = segment.paramName ? params[segment.paramName] : undefined;
                return label ? [{ label }] : [];
            }
            if (segment.type === 'routeParamLink') {
                const paramName = segment.paramName;
                const label = segment.label ?? (paramName ? params[paramName] : undefined);
                const childPathTemplate = segment.childPathTemplate;
                if (!label || !childPathTemplate) return [];
                const childPath = expandChildPathTemplate(childPathTemplate, params);
                return [{ label, to: buildSetupPageChildPath(route.pageId, childPath, currentFrontendAppId) }];
            }
            return segment.label ? [{ label: segment.label }] : [];
        });
    }, [currentFrontendAppId, matchedChildRoute]);

    // Memoized page label lookup
    const currentPageLabel = useMemo(() => {
        if (isHome) return 'Setup & Configuration';
        if (matchedChildRoute?.route.pageLabel) return matchedChildRoute.route.pageLabel;

        const pages = SetupRegistry.getPages(currentFrontendAppId);
        const currentPage = pages.find(p => p.path === location.pathname);
        if (currentPage) return currentPage.label;

        // For detail sub-pages, show the parent label
        if (isDetailSubPage) {
            const parentPage = pages.find(p => p.path && location.pathname.startsWith(`${p.path}/`));
            if (parentPage) return parentPage.label;
            const parentSegment = location.pathname.slice(setupBasePath?.length ?? 0).split('/').filter(Boolean)[0] || '';
            return parentSegment.charAt(0).toUpperCase() + parentSegment.slice(1);
        }

        // Fallback: capitalize last segment
        const segment = location.pathname.split('/').pop() || '';
        return segment.charAt(0).toUpperCase() + segment.slice(1);
    }, [location.pathname, isHome, isDetailSubPage, matchedChildRoute, setupBasePath, currentFrontendAppId]);

    if (!setupBasePath) {
        if (appsLoading) {
            return LazyFallback;
        }
        return <Navigate to="/" replace />;
    }

    return (
        <div className="max-w-7xl mx-auto pt-6">
            <div className="flex items-center gap-2 mb-6 text-sm text-slate-500">
                <Link to={setupBasePath} className="hover:text-blue-600 flex items-center gap-1">
                    <SettingsIcon size={14} /> Setup
                </Link>
                {!isHome && childBreadcrumbSegments.length > 0 ? (
                    <>
                        {childBreadcrumbSegments.map((segment, index) => {
                            const isLast = index === childBreadcrumbSegments.length - 1;
                            return (
                                <React.Fragment key={`${segment.label}:${index}`}>
                                    <span>/</span>
                                    {segment.to && !isLast ? (
                                        <Link to={segment.to} className="hover:text-blue-600">{segment.label}</Link>
                                    ) : (
                                        <span className={isLast ? 'text-slate-800 font-medium' : undefined}>{segment.label}</span>
                                    )}
                                </React.Fragment>
                            );
                        })}
                    </>
                ) : !isHome && (
                    <>
                        <span>/</span>
                        <span className="text-slate-800 font-medium">
                            {currentPageLabel}
                        </span>
                    </>
                )}
            </div>

            {/* Detail sub-pages render their own header */}
            {!isDetailSubPage && (
                <h1 className="text-2xl font-bold text-slate-800 mb-6">
                    {currentPageLabel}
                </h1>
            )}

            <DynamicSetupRoutes appId={currentFrontendAppId} />
        </div>
    );
};
