// Authentication Middleware
const pool = require('../db');
const { teamToIvanti } = require('../helpers/teams');

// Require authenticated user — no parameters needed, pool is imported directly
function requireAuth() {
    return async (req, res, next) => {
        const sessionId = req.cookies?.session_id;

        if (!sessionId) {
            return res.status(401).json({ error: 'Authentication required' });
        }

        try {
            const { rows } = await pool.query(
                `SELECT s.*, s.impersonate_user_id,
                        u.id as user_id, u.username, u.email, u.role, u.user_group, u.bu_teams, u.is_active
                 FROM sessions s
                 JOIN users u ON s.user_id = u.id
                 WHERE s.session_id = $1 AND s.expires_at > NOW()`,
                [sessionId]
            );

            const session = rows[0];

            if (!session) {
                return res.status(401).json({ error: 'Session expired or invalid' });
            }

            if (!session.is_active) {
                return res.status(401).json({ error: 'Account is disabled' });
            }

            // Store the real admin identity (always the session owner)
            req.realUser = {
                id: session.user_id,
                username: session.username,
                email: session.email,
                role: session.role,
                group: session.user_group,
                teams: session.bu_teams ? session.bu_teams.split(',').filter(Boolean) : []
            };

            // If impersonating, load the target user's identity
            if (session.impersonate_user_id) {
                const { rows: targetRows } = await pool.query(
                    `SELECT id, username, email, role, user_group, bu_teams, is_active FROM users WHERE id = $1`,
                    [session.impersonate_user_id]
                );
                const target = targetRows[0];

                if (target && target.is_active) {
                    req.user = {
                        id: target.id,
                        username: target.username,
                        email: target.email,
                        role: target.role,
                        group: target.user_group,
                        teams: target.bu_teams ? target.bu_teams.split(',').filter(Boolean) : []
                    };
                    req.impersonating = true;
                } else {
                    // Target user no longer valid — clear impersonation and use real user
                    await pool.query(`UPDATE sessions SET impersonate_user_id = NULL WHERE session_id = $1`, [sessionId]);
                    req.user = req.realUser;
                    req.impersonating = false;
                }
            } else {
                req.user = req.realUser;
                req.impersonating = false;
            }

            next();
        } catch (err) {
            console.error('Auth middleware error:', err);
            return res.status(500).json({ error: 'Authentication error' });
        }
    };
}

// Require specific group(s)
function requireGroup(...allowedGroups) {
    return (req, res, next) => {
        if (!req.user) {
            return res.status(401).json({ error: 'Authentication required' });
        }

        if (!allowedGroups.includes(req.user.group)) {
            return res.status(403).json({
                error: 'Insufficient permissions',
                required: allowedGroups,
                current: req.user.group
            });
        }

        next();
    };
}

// Require team assignment — enforces team-scoped data access.
// Admin group bypasses (req.teamScope = null means "no filter").
// However, if an Admin passes a ?teams= query param (via the scope toggle),
// it is respected as a voluntary filter.
// Non-admin users without teams get 403.
// Non-admin users with teams get req.teamScope = { short: [...], ivanti: [...] }.
function requireTeam() {
    return (req, res, next) => {
        if (!req.user) {
            return res.status(401).json({ error: 'Authentication required' });
        }

        // Admin bypass — but respect optional ?teams= param as voluntary scope
        if (req.user.group === 'Admin') {
            const teamsParam = req.query?.teams;
            if (teamsParam) {
                const teams = teamsParam.split(',').map(t => t.trim()).filter(Boolean);
                if (teams.length > 0) {
                    req.teamScope = {
                        short: teams,
                        ivanti: teams.map(t => teamToIvanti(t))
                    };
                    return next();
                }
            }
            req.teamScope = null;
            return next();
        }

        // No teams assigned — block access
        if (!req.user.teams || req.user.teams.length === 0) {
            return res.status(403).json({
                error: 'No team assignment. Contact an administrator to assign BU teams to your account.',
                code: 'NO_TEAM_ASSIGNMENT'
            });
        }

        // Build scope with both naming conventions
        req.teamScope = {
            short: req.user.teams,
            ivanti: req.user.teams.map(t => teamToIvanti(t))
        };

        next();
    };
}

module.exports = { requireAuth, requireGroup, requireTeam };
