const jwt = require('jsonwebtoken');
const db = require('../db');

const protect = async (req, res, next) => {
    let token;

    if (
        (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) ||
        req.query.token
    ) {
        try {
            // Get token from header or query
            if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
                token = req.headers.authorization.split(' ')[1];
            } else {
                token = req.query.token;
            }

            // Verify token
            const decoded = jwt.verify(token, process.env.JWT_SECRET);

            // Get user from the token
            const userResult = await db.query('SELECT id, role, is_student, name, email, training_completed, current_mission, session_token, mobile_session_token FROM users WHERE id = ?', [decoded.id]);

            if (userResult.rows.length === 0) {
                return res.status(401).json({ message: 'Not authorized, user not found' });
            }

            const user = userResult.rows[0];

            // Single-device enforcement: Check if session token matches based on platform
            let isValidSession = true;

            if (decoded.type === 'mobile') {
                if (decoded.sessionToken && user.mobile_session_token && decoded.sessionToken !== user.mobile_session_token) {
                    isValidSession = false;
                }
            } else {
                // Default to web check
                if (decoded.sessionToken && user.session_token && decoded.sessionToken !== user.session_token) {
                    isValidSession = false;
                }
            }

            if (!isValidSession) {
                return res.status(401).json({
                    message: 'Session expired. Your account was logged in from another device.',
                    code: 'SESSION_INVALIDATED'
                });
            }

            req.user = user;
            next();
        } catch (error) {
            console.error(error);
            res.status(401).json({ message: 'Not authorized' });
        }
    }


    if (!token) {
        res.status(401).json({ message: 'Not authorized, no token' });
    }
};

const authorize = (...roles) => {
    return (req, res, next) => {
        if (!roles.includes(req.user.role)) {
            return res.status(403).json({
                message: `User role ${req.user.role} is not authorized to access this route`
            });
        }
        next();
    };
};

const admin = authorize('admin');

const requireTraining = (req, res, next) => {
    // Training requirement disabled - all authenticated users can access
    next();
};

// Optional auth: populates req.user if token is present, but allows anonymous access
const optionalAuth = async (req, res, next) => {
    let token;

    if (
        (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) ||
        req.query.token
    ) {
        try {
            if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
                token = req.headers.authorization.split(' ')[1];
            } else {
                token = req.query.token;
            }
            const decoded = jwt.verify(token, process.env.JWT_SECRET);
            const userResult = await db.query('SELECT id, role, name, email FROM users WHERE id = ?', [decoded.id]);
            if (userResult.rows.length > 0) {
                req.user = userResult.rows[0];
            }
        } catch (error) {
            // Token invalid - just continue without user
        }
    }
    next();
};

module.exports = { protect, authorize, admin, requireTraining, optionalAuth };
