const logger = require('../utils/logger');
const nocodbService = require('../services/nocodb');

// Helper function to check if a temp user has expired
const checkTempUserExpiration = async (req, res) => {
    if (req.session?.userType === 'temp' && req.session?.userEmail) {
        try {
            const user = await nocodbService.getUserByEmail(req.session.userEmail);
            if (user) {
                const expiration = user.ExpiresAt || user.expiresAt || user.Expiration || user.expiration;
                if (expiration) {
                    const expirationDate = new Date(expiration);
                    const now = new Date();
                    
                    if (now > expirationDate) {
                        logger.warn(`Expired temp user session detected: ${req.session.userEmail}, expired: ${expiration}`);
                        
                        // Destroy the session
                        req.session.destroy((err) => {
                            if (err) {
                                logger.error('Session destroy error:', err);
                            }
                        });
                        
                        if (req.xhr || req.headers.accept?.indexOf('json') > -1) {
                            return res.status(401).json({ 
                                success: false, 
                                error: 'Account has expired. Please contact an administrator.',
                                expired: true
                            });
                        } else {
                            return res.redirect('/login.html?expired=true');
                        }
                    }
                }
            }
        } catch (error) {
            logger.error('Error checking temp user expiration:', error.message);
            // Don't fail the request on database errors, just log it
        }
    }
    return null; // No expiration issue
};

const requireAuth = async (req, res, next) => {
    const isAuthenticated = (req.session && req.session.authenticated) || 
                           (req.session && req.session.userId && req.session.userEmail);
    
    if (isAuthenticated) {
        // Check if temp user has expired
        const expirationResponse = await checkTempUserExpiration(req, res);
        if (expirationResponse) {
            return; // Response already sent by checkTempUserExpiration
        }
        
        // Set up req.user object for controllers that expect it
        req.user = {
            id: req.session.userId,
            email: req.session.userEmail,
            isAdmin: req.session.isAdmin || false,
            userType: req.session.userType
        };
        
        next();
    } else {
        logger.warn('Unauthorized access attempt', {
            ip: req.ip,
            path: req.path,
            userAgent: req.get('User-Agent'),
            referer: req.get('Referer'), // Add referer to see where requests come from
            method: req.method,
            timestamp: new Date().toISOString()
        });
        
        // Check if this is an auto-refresh request
        if (req.headers['x-requested-with'] === 'XMLHttpRequest' || 
            req.path.includes('/api/locations')) {
            return res.status(401).json({
                authenticated: false,
                error: 'Session expired',
                isAutoRefresh: true
            });
        }
        
        if (req.xhr || req.headers.accept?.indexOf('json') > -1) {
            res.status(401).json({ 
                success: false, 
                error: 'Authentication required' 
            });
        } else {
            res.redirect('/login.html');
        }
    }
};

const requireAdmin = async (req, res, next) => {
    // Check for both authentication patterns used in your app
    const isAuthenticated = (req.session && req.session.authenticated) || 
                           (req.session && req.session.userId && req.session.userEmail);
    
    if (isAuthenticated && req.session.isAdmin) {
        // Check if temp user has expired
        const expirationResponse = await checkTempUserExpiration(req, res);
        if (expirationResponse) {
            return; // Response already sent by checkTempUserExpiration
        }
        
        // Set up req.user object for controllers that expect it
        req.user = {
            id: req.session.userId,
            email: req.session.userEmail,
            isAdmin: req.session.isAdmin || false,
            userType: req.session.userType
        };
        
        next();
    } else {
        logger.warn('Unauthorized admin access attempt', {
            ip: req.ip,
            path: req.path,
            user: req.session?.userEmail || 'anonymous',
            userAgent: req.get('User-Agent')
        });
        
        if (req.xhr || req.headers.accept?.indexOf('json') > -1) {
            res.status(403).json({ 
                success: false, 
                error: 'Admin access required' 
            });
        } else {
            res.redirect('/login.html');
        }
    }
};

const requireNonTemp = async (req, res, next) => {
    const isAuthenticated = (req.session && req.session.authenticated) || 
                           (req.session && req.session.userId && req.session.userEmail);
    
    if (isAuthenticated && req.session.userType !== 'temp') {
        // Check if temp user has expired (shouldn't happen here, but for safety)
        const expirationResponse = await checkTempUserExpiration(req, res);
        if (expirationResponse) {
            return; // Response already sent by checkTempUserExpiration
        }
        
        // Set up req.user object for controllers that expect it
        req.user = {
            id: req.session.userId,
            email: req.session.userEmail,
            isAdmin: req.session.isAdmin || false,
            userType: req.session.userType
        };
        
        next();
    } else {
        logger.warn('Temp user access denied', {
            ip: req.ip,
            path: req.path,
            user: req.session?.userEmail || 'anonymous',
            userType: req.session?.userType || 'unknown'
        });
        
        if (req.xhr || req.headers.accept?.indexOf('json') > -1) {
            res.status(403).json({ 
                success: false, 
                error: 'Access denied for temporary users' 
            });
        } else {
            res.redirect('/');
        }
    }
};

const requireDeletePermission = async (req, res, next) => {
    const isAuthenticated = (req.session && req.session.authenticated) || 
                           (req.session && req.session.userId && req.session.userEmail);
    
    // Only admins and regular users can delete, not temps
    if (isAuthenticated && req.session.userType !== 'temp') {
        // Check if temp user has expired (shouldn't happen here, but for safety)
        const expirationResponse = await checkTempUserExpiration(req, res);
        if (expirationResponse) {
            return; // Response already sent by checkTempUserExpiration
        }
        
        next();
    } else {
        logger.warn('Delete permission denied', {
            ip: req.ip,
            path: req.path,
            user: req.session?.userEmail || 'anonymous',
            userType: req.session?.userType || 'unknown'
        });
        
        res.status(403).json({ 
            success: false, 
            error: 'Delete permission denied' 
        });
    }
};

module.exports = {
    requireAuth,
    requireAdmin,
    requireNonTemp,
    requireDeletePermission
};