import { PrivilegeChecker } from '../core/PageManager/pageInterface';
import { getUserDataCache } from './userCache';
import type { PermissionContext } from '../hooks/usePermissions';

/**
 * Privilege Checkers
 * 
 * Read-only access to user data for privilege checking.
 * Does not manage user data storage - that's handled by authentication hooks.
 * 
 * Now supports both client-side checks (roles, localStorage) and backend RBAC integration.
 */

// Function to get current user role labels from sessionStorage cache
const getCurrentUserRoleLabels = (): string[] => {
    const userData = getUserDataCache();
    return Array.isArray(userData?.roleLabels) ? userData.roleLabels : [];
};

// Generic privilege checker for localStorage-based data with expiration
export const createLocalStoragePrivilegeChecker = (
    dataKey: string,
    timestampKey: string,
    expirationHours: number = 24
): PrivilegeChecker => {
    return (): boolean => {
        try {
            const savedData = localStorage.getItem(dataKey);
            const timestamp = localStorage.getItem(timestampKey);
            
            if (savedData && timestamp) {
                const dataTime = parseInt(timestamp);
                const now = Date.now();
                const hoursDiff = (now - dataTime) / (1000 * 60 * 60);
                
                return hoursDiff < expirationHours;
            }
            
            return false;
        } catch (error) {
            console.error(`Error checking privilege for ${dataKey}:`, error);
            return false;
        }
    };
};

// Generic privilege checker for user roles/permissions
export const createRolePrivilegeChecker = (
    requiredRoles: string[],
    getUserRoles: () => string[] | Promise<string[]>
): PrivilegeChecker => {
    return async (): Promise<boolean> => {
        try {
            const userRoles = await getUserRoles();
            const hasRequiredRole = requiredRoles.some(role => userRoles.includes(role));
            
            return hasRequiredRole;
        } catch (error) {
            console.error('Error checking role privilege:', error);
            return false;
        }
    };
};

// Generic privilege checker for feature flags
export const createFeatureFlagChecker = (
    featureFlag: string,
    getFeatureFlags: () => Record<string, boolean> | Promise<Record<string, boolean>>
): PrivilegeChecker => {
    return async (): Promise<boolean> => {
        try {
            const flags = await getFeatureFlags();
            return flags[featureFlag] === true;
        } catch (error) {
            console.error(`Error checking feature flag ${featureFlag}:`, error);
            return false;
        }
    };
};

// Generic privilege checker for authentication status
export const createAuthPrivilegeChecker = (
    isAuthenticated: () => boolean | Promise<boolean>
): PrivilegeChecker => {
    return async (): Promise<boolean> => {
        try {
            return await isAuthenticated();
        } catch (error) {
            console.error('Error checking authentication status:', error);
            return false;
        }
    };
};

// Helper function to create custom privilege checkers
export const createCustomPrivilegeChecker = (
    checkFunction: () => boolean | Promise<boolean>
): PrivilegeChecker => {
    return checkFunction;
};

/**
 * Create a privilege checker that uses backend RBAC permissions
 * This integrates privilegeCheckers with usePermissions for backend-controlled access
 * 
 * @param canViewFunction - The canView function from usePermissions hook
 * @param context - Permission context ('UI', 'DATA', or 'RESOURCE')
 * @param item - The item/resource path to check permissions for
 * @returns A PrivilegeChecker function that checks backend RBAC permissions
 */
export const createRBACPrivilegeChecker = (
    canViewFunction: (context: PermissionContext, item: string) => Promise<boolean>,
    context: PermissionContext,
    item: string
): PrivilegeChecker => {
    return async (): Promise<boolean> => {
        try {
            return await canViewFunction(context, item);
        } catch (error) {
            console.error(`Error checking RBAC privilege for ${context}:${item}:`, error);
            return false;
        }
    };
};

/**
 * Create a privilege checker that combines RBAC with client-side role checks
 * First checks backend RBAC, then falls back to client-side role check if RBAC allows
 * 
 * @param canViewFunction - The canView function from usePermissions hook
 * @param context - Permission context ('UI', 'DATA', or 'RESOURCE')
 * @param item - The item/resource path to check permissions for
 * @param requiredRoles - Fallback client-side roles to check if RBAC passes
 * @returns A PrivilegeChecker function that checks both RBAC and roles
 */
export const createCombinedPrivilegeChecker = (
    canViewFunction: (context: PermissionContext, item: string) => Promise<boolean>,
    context: PermissionContext,
    item: string,
    requiredRoles: string[]
): PrivilegeChecker => {
    return async (): Promise<boolean> => {
        try {
            // First check backend RBAC
            const hasRBACAccess = await canViewFunction(context, item);
            if (!hasRBACAccess) {
                return false;
            }
            
            // If RBAC allows, also check client-side roles as additional validation
            const userRoleLabels = getCurrentUserRoleLabels();
            const hasRequiredRole = requiredRoles.some(role => userRoleLabels.includes(role));
            if (hasRequiredRole) {
                return true;
            }
            
            // If no role match, still allow if RBAC said yes (backend is source of truth)
            return hasRBACAccess;
        } catch (error) {
            console.error(`Error checking combined privilege for ${context}:${item}:`, error);
            return false;
        }
    };
};

/**
 * Helper to create RBAC-based privilege checkers for page data
 * These checkers will use backend RBAC permissions via usePermissions
 * 
 * Usage in page data:
 * import { createRBACPageChecker } from '@/utils/privilegeCheckers';
 * 
 * // In PageManager, initialize with canView function:
 * const rbacCheckers = createRBACPageCheckers(canView);
 * 
 * // In page data:
 * privilegeChecker: rbacCheckers.forPage('administration/workflows')
 */
export const createRBACPageCheckers = (
    canViewFunction: (context: PermissionContext, item: string) => Promise<boolean>
) => {
    return {
        /**
         * Create a privilege checker for a specific page path
         * Checks backend RBAC permissions for UI context
         */
        forPage: (pagePath: string): PrivilegeChecker => {
            return createRBACPrivilegeChecker(canViewFunction, 'UI', pagePath);
        },
        
        /**
         * Create a privilege checker that combines RBAC with role requirements
         * First checks backend RBAC, then validates user role
         */
        forPageWithRole: (
            pagePath: string,
            requiredRoles: string[]
        ): PrivilegeChecker => {
            return createCombinedPrivilegeChecker(canViewFunction, 'UI', pagePath, requiredRoles);
        },
        
        /**
         * Create a privilege checker for a data resource
         * Checks backend RBAC permissions for DATA context
         */
        forData: (resourcePath: string): PrivilegeChecker => {
            return createRBACPrivilegeChecker(canViewFunction, 'DATA', resourcePath);
        },
        
        /**
         * Create a privilege checker for a UI resource
         * Checks backend RBAC permissions for UI context
         */
        forUI: (resourcePath: string): PrivilegeChecker => {
            return createRBACPrivilegeChecker(canViewFunction, 'UI', resourcePath);
        }
    };
};

// Predefined privilege checkers for common use cases
export const privilegeCheckers = {
    // Speech signup checker (existing functionality)
    speechSignup: createLocalStoragePrivilegeChecker(
        'speechSignUpData',
        'speechSignUpTimestamp',
        24
    ),
    
    // Admin role checker - for admin and sysadmin users
    adminRole: createRolePrivilegeChecker(
        ['admin', 'sysadmin'],
        () => {
            const userRoleLabels = getCurrentUserRoleLabels();
            return Promise.resolve(userRoleLabels);
        }
    ),
    
    // Sysadmin role checker - for sysadmin only
    sysadminRole: createRolePrivilegeChecker(
        ['sysadmin'],
        () => {
            const userRoleLabels = getCurrentUserRoleLabels();
            return Promise.resolve(userRoleLabels);
        }
    ),
    
    // Premium user checker
    premiumUser: createLocalStoragePrivilegeChecker(
        'premiumUserData',
        'premiumUserTimestamp',
        24 * 30 // 30 days
    ),
    
    // Feature flag checker
    betaFeatures: createFeatureFlagChecker(
        'betaFeatures',
        () => {
            const flags = JSON.parse(localStorage.getItem('featureFlags') || '{}');
            return Promise.resolve(flags);
        }
    ),
    
    // Authentication checker
    authenticated: createAuthPrivilegeChecker(
        () => {
            const token = localStorage.getItem('authToken');
            return Promise.resolve(!!token);
        }
    ),
    
    // User role checker - for user, admin, and sysadmin access
    userRole: createRolePrivilegeChecker(
        ['user', 'admin', 'sysadmin'],
        () => {
            const userRoleLabels = getCurrentUserRoleLabels();
            return Promise.resolve(userRoleLabels);
        }
    ),
    
    // Viewer role checker - for viewer, user, admin, and sysadmin access (all levels)
    viewerRole: createRolePrivilegeChecker(
        ['viewer', 'user', 'admin', 'sysadmin'],
        () => {
            const userRoleLabels = getCurrentUserRoleLabels();
            return Promise.resolve(userRoleLabels);
        }
    ),
    
    // Subscription checker - for paid features
    hasSubscription: createLocalStoragePrivilegeChecker(
        'subscriptionData',
        'subscriptionTimestamp',
        24 * 7 // 7 days
    ),
    
    // Mandate checker - for users who have submitted their mandate
    hasMandate: createLocalStoragePrivilegeChecker(
        'mandateData',
        'mandateTimestamp',
        24 * 30 // 30 days
    ),
    
    // Always allow access (for public pages)
    alwaysAllow: createCustomPrivilegeChecker(() => true),
    
    // Never allow access (for disabled features)
    neverAllow: createCustomPrivilegeChecker(() => false)
};
