const {
    getEntraUsers,
    getAllMfaRegistrationDetails,
    getAzureGroups,
    getAzureGroupMembers,
    getEntraUserGroups,
    getDirectoryRolesWithMembers,
    addGroupMember,
    removeGroupMember,
    getUserEntraProfile,
    getUserLicenseDetails,
    getEntraSubscribedSkus,
    getUserSignInActivity,
    getUserSignInRisk,
    getConditionalAccessPolicies,
    invalidateUserSessions,
} = require('../services/graph.service');
const Database = require('better-sqlite3');
const DB_PATH = process.env.DATABASE_PATH || './database.sqlite';

/**
 * GET /api/entra/users
 * Returns all Entra users merged with MFA registration info.
 */
exports.getUsers = async (req, res) => {
    try {
        const [users, mfaDetails] = await Promise.all([
            getEntraUsers(),
            getAllMfaRegistrationDetails().catch(() => []), // graceful fallback if AuditLog permission missing
        ]);

        // Build MFA lookup map by userPrincipalName
        const mfaMap = {};
        for (const m of mfaDetails) {
            mfaMap[m.userPrincipalName?.toLowerCase()] = m;
        }

        const merged = users.map(u => {
            const mfa = mfaMap[u.userPrincipalName?.toLowerCase()] || null;
            return {
                id:              u.id,
                displayName:     u.displayName,
                mail:            u.mail || u.userPrincipalName,
                userPrincipalName: u.userPrincipalName,
                jobTitle:        u.jobTitle || null,
                department:      u.department || null,
                accountEnabled:  u.accountEnabled,
                mfaRegistered:   mfa ? mfa.isMfaRegistered : null,
                mfaCapable:      mfa ? mfa.isMfaCapable : null,
                mfaMethods:      mfa ? (mfa.methodsRegistered || []) : [],
            };
        });

        res.json({ success: true, data: merged });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * GET /api/entra/users/:id/groups
 * Returns groups for a specific user.
 */
exports.getUserGroups = async (req, res) => {
    try {
        const groups = await getEntraUserGroups(req.params.id);
        res.json({ success: true, data: groups });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * GET /api/entra/groups
 * Returns all groups (without members — lazy-loaded per group).
 */
exports.getGroups = async (req, res) => {
    try {
        const groups = await getAzureGroups();
        res.json({ success: true, data: groups });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * GET /api/entra/groups/:id/members
 * Returns members of a specific group.
 */
exports.getGroupMembers = async (req, res) => {
    try {
        const members = await getAzureGroupMembers(req.params.id);
        res.json({ success: true, data: members });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * POST /api/entra/groups/:id/members
 * Adds a user to a group. Body: { userId }
 * Requires GroupMember.ReadWrite.All
 */
exports.addGroupMember = async (req, res) => {
    const { userId } = req.body;
    if (!userId) return res.status(400).json({ success: false, message: 'userId fehlt' });
    try {
        await addGroupMember(req.params.id, userId);
        res.json({ success: true });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * DELETE /api/entra/groups/:id/members/:userId
 * Removes a user from a group.
 * Requires GroupMember.ReadWrite.All
 */
exports.removeGroupMember = async (req, res) => {
    try {
        await removeGroupMember(req.params.id, req.params.userId);
        res.json({ success: true });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

/**
 * GET /api/entra/roles
 * Returns all activated directory roles with their members.
 */
exports.getRoles = async (req, res) => {
    try {
        const roles = await getDirectoryRolesWithMembers();
        res.json({ success: true, data: roles });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.getUserProfile = async (req, res) => {
    try {
        const profile = await getUserEntraProfile(req.params.azureId);
        res.json({ success: true, data: profile });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.getUserLicenses = async (req, res) => {
    try {
        const [licenses, skus] = await Promise.all([
            getUserLicenseDetails(req.params.azureId),
            getEntraSubscribedSkus().catch(() => []),
        ]);
        const skuMap = {};
        for (const s of skus) skuMap[s.skuId] = s;

        // Preise aus license_prices Tabelle laden
        let priceRows = [];
        try {
            const db = new Database(DB_PATH);
            priceRows = db.prepare('SELECT sku_part_number, display_name, price_per_month FROM license_prices').all();
            db.close();
        } catch (_) {}

        const enriched = licenses.map(l => {
            const skuPart = l.skuPartNumber || '';
            const skuPartUpper = skuPart.toUpperCase();
            // Exact match zuerst, dann partial match
            const priceRow = priceRows.find(p => p.sku_part_number.toUpperCase() === skuPartUpper)
                || priceRows.find(p => skuPartUpper.includes(p.sku_part_number.toUpperCase()) || p.sku_part_number.toUpperCase().includes(skuPartUpper));
            return {
                ...l,
                skuInfo: skuMap[l.skuId] || null,
                price_per_month: priceRow?.price_per_month ?? null,
                price_display_name: priceRow?.display_name ?? null,
            };
        });
        res.json({ success: true, data: enriched });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.getUserSignInLog = async (req, res) => {
    try {
        const logs = await getUserSignInActivity(req.params.azureId);
        res.json({ success: true, data: logs });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.getUserSignInRisk = async (req, res) => {
    try {
        const risk = await getUserSignInRisk(req.params.azureId);
        res.json({ success: true, data: risk });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.getCAP = async (req, res) => {
    try {
        const policies = await getConditionalAccessPolicies();
        res.json({ success: true, data: policies });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};

exports.invalidateSessions = async (req, res) => {
    try {
        await invalidateUserSessions(req.params.azureId);
        res.json({ success: true, message: 'Sessions invalidiert. Benutzer muss sich neu anmelden.' });
    } catch (e) {
        res.status(500).json({ success: false, message: e.message });
    }
};
