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) {
                        console.warn(`Expired temp user session detected: ${req.session.userEmail}, expired: ${expiration}`);

                        // Destroy the session
                        req.session.destroy((err) => {
                            if (err) {
                                console.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) {
            console.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 || 'user',
            name: req.session.userName || req.session.user_name || null
        };

        next();
    } else {
        console.warn('Unauthorized access attempt', {
            ip: req.ip,
            path: req.path,
            userAgent: req.get('User-Agent'),
            method: req.method,
            timestamp: new Date().toISOString()
        });

        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) => {
    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 || 'user',
            name: req.session.userName || req.session.user_name || null
        };

        next();
    } else {
        console.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 || 'user',
            name: req.session.userName || req.session.user_name || null
        };

        next();
    } else {
        console.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('/');
        }
    }
};

// Optional authentication - sets req.user if authenticated, but doesn't block if not
const optionalAuth = 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 || 'user',
            name: req.session.userName || req.session.user_name || null
        };
    }

    // Continue regardless of authentication status
    next();
};

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