const License = require('../models/License');
const { asyncHandler } = require('../middleware/errorHandler');
const { getEntraSubscribedSkus } = require('../services/graph.service');

// Friendly display names for common Microsoft SKU part numbers
const SKU_NAMES = {
    // Microsoft 365
    SPB: 'Microsoft 365 Business Premium',
    O365_BUSINESS_PREMIUM: 'Microsoft 365 Business Standard',
    O365_BUSINESS_ESSENTIALS: 'Microsoft 365 Business Basic',
    SMB_BUSINESS: 'Microsoft 365 Apps for Business',
    OFFICESUBSCRIPTION: 'Microsoft 365 Apps for Enterprise',
    ENTERPRISEPACK: 'Microsoft 365 E3',
    ENTERPRISEPREMIUM: 'Microsoft 365 E5',
    SPE_E3: 'Microsoft 365 E3',
    SPE_E5: 'Microsoft 365 E5',
    M365EDU_A3_FACULTY: 'Microsoft 365 A3 (Bildung)',
    M365EDU_A5_FACULTY: 'Microsoft 365 A5 (Bildung)',
    // Exchange
    EXCHANGESTANDARD: 'Exchange Online (Plan 1)',
    EXCHANGEENTERPRISE: 'Exchange Online (Plan 2)',
    EXCHANGE_S_DESKLESS: 'Exchange Online Kiosk',
    EXCHANGEARCHIVE_ADDON: 'Exchange Online Archivierung',
    // Teams & Kommunikation
    TEAMS_ESSENTIALS: 'Microsoft Teams Essentials',
    MCOSTANDARD: 'Skype for Business Online (Plan 2)',
    MCOEV: 'Microsoft Teams Phone Standard',
    MCOEV_VIRTUALUSER: 'Microsoft Teams Phone Resource Account',
    MCOMEETADV: 'Microsoft Teams Audio Conferencing',
    MCOMEETADV_BYON: 'Teams Audio Conferencing (BYOT)',
    MCOTEAMS_ESSENTIALS: 'Microsoft Teams Essentials',
    // Intune & Security
    INTUNE_A: 'Microsoft Intune Plan 1',
    INTUNE_P2: 'Microsoft Intune Plan 2',
    AAD_PREMIUM: 'Azure AD Premium P1',
    AAD_PREMIUM_P2: 'Azure AD Premium P2',
    EMS: 'Enterprise Mobility + Security E3',
    EMSPREMIUM: 'Enterprise Mobility + Security E5',
    DEFENDER_ENDPOINT_P1: 'Microsoft Defender for Endpoint P1',
    MDATP_XPLAT: 'Microsoft Defender for Endpoint P2',
    ATP_ENTERPRISE: 'Microsoft Defender for Office 365 (Plan 1)',
    THREAT_INTELLIGENCE: 'Microsoft Defender for Office 365 (Plan 2)',
    // Power Platform
    POWER_BI_PRO: 'Power BI Pro',
    POWER_BI_PREMIUM_PER_USER: 'Power BI Premium Per User',
    POWERAPPS_PER_USER: 'Power Apps Per User Plan',
    FLOW_PER_USER: 'Power Automate Per User Plan',
    FLOW_FREE: 'Power Automate Free',
    DYN365_ENTERPRISE_PLAN1: 'Dynamics 365 Customer Engagement Plan',
    // Windows & Devices
    WIN10_PRO_ENT_SUB: 'Windows 10/11 Enterprise E3',
    WIN_ENT_E5: 'Windows 10/11 Enterprise E5',
    // Project & Visio
    PROJECTPROFESSIONAL: 'Project Plan 5',
    PROJECTPREMIUM: 'Project Plan 3',
    PROJECT_PLAN1: 'Project Plan 1',
    VISIOCLIENT: 'Visio Plan 2',
    VISIOONLINE_PLAN1: 'Visio Plan 1',
    // Sonstiges
    CCIBOTS_PRIVPREV_VIRAL: 'Microsoft Copilot für Microsoft 365',
    MICROSOFT_COPILOT_SECP: 'Copilot for Security',
    RIGHTSMANAGEMENT: 'Azure Information Protection Plan 1',
    RIGHTSMANAGEMENT_PREMIUM: 'Azure Information Protection Plan 2',
    CRMSTANDARD: 'Microsoft Dynamics CRM Online',
    STREAM: 'Microsoft Stream',
};

class LicenseController {
    static getAll = asyncHandler(async (req, res) => {
        const licenses = License.getAll();
        res.json({ status: 'success', data: licenses });
    });

    static getById = asyncHandler(async (req, res) => {
        const license = License.getById(parseInt(req.params.id));
        if (!license) {
            return res.status(404).json({ status: 'error', message: 'Lizenz nicht gefunden' });
        }
        res.json({ status: 'success', data: license });
    });

    static create = asyncHandler(async (req, res) => {
        const { name, vendor, license_type, product_key, seats, purchase_date, expiry_date, cost, notes } = req.body;
        if (!name) {
            return res.status(400).json({ status: 'error', message: 'Name ist erforderlich' });
        }
        const license = License.create({
            name, vendor, license_type, product_key, seats, purchase_date, expiry_date, cost, notes,
            created_by_user_id: req.user.id,
        });
        res.status(201).json({ status: 'success', data: license });
    });

    static update = asyncHandler(async (req, res) => {
        const existing = License.getById(parseInt(req.params.id));
        if (!existing) {
            return res.status(404).json({ status: 'error', message: 'Lizenz nicht gefunden' });
        }
        const license = License.update(parseInt(req.params.id), req.body);
        res.json({ status: 'success', data: license });
    });

    static delete = asyncHandler(async (req, res) => {
        const existing = License.getById(parseInt(req.params.id));
        if (!existing) {
            return res.status(404).json({ status: 'error', message: 'Lizenz nicht gefunden' });
        }
        License.delete(parseInt(req.params.id));
        res.json({ status: 'success', message: 'Lizenz gelöscht' });
    });

    static getStatistics = asyncHandler(async (req, res) => {
        const stats = License.getStatistics();
        res.json({ status: 'success', data: stats });
    });

    static importFromEntra = asyncHandler(async (req, res) => {
        const skus = await getEntraSubscribedSkus();

        const existing = License.getAll();
        // Map by sku_id for fast dedup; fallback to name+vendor
        const existingBySkuId = new Map(existing.filter(l => l.sku_id).map(l => [l.sku_id, l]));
        const existingByName  = new Set(existing.map(l => `${l.name}||${l.vendor}`));

        let imported = 0;
        let updated  = 0;
        let skipped  = 0;
        const errors = [];

        for (const sku of skus) {
            try {
                const seats = sku.prepaidUnits?.enabled || 0;
                if (seats === 0) { skipped++; continue; }

                const name  = SKU_NAMES[sku.skuPartNumber] || sku.skuPartNumber;
                const notes = `SKU: ${sku.skuPartNumber} | Genutzt: ${sku.consumedUnits || 0} / ${seats} | Status: ${sku.capabilityStatus}`;

                // Already exists by sku_id → update seats/notes
                if (existingBySkuId.has(sku.skuId)) {
                    License.update(existingBySkuId.get(sku.skuId).id, { seats, notes });
                    updated++;
                    continue;
                }

                // Already exists by name+vendor (imported before sku_id existed)
                if (existingByName.has(`${name}||Microsoft`)) {
                    // Link sku_id retroactively
                    const match = existing.find(l => l.name === name && l.vendor === 'Microsoft');
                    if (match) License.update(match.id, { seats, notes, sku_id: sku.skuId });
                    updated++;
                    continue;
                }

                License.create({
                    name, vendor: 'Microsoft', license_type: 'subscription',
                    seats, notes, sku_id: sku.skuId,
                    created_by_user_id: req.user.id,
                });
                existingByName.add(`${name}||Microsoft`);
                imported++;
            } catch (err) {
                errors.push(sku.skuPartNumber + ': ' + err.message);
            }
        }

        res.json({ status: 'success', data: { imported, updated, skipped, errors } });
    });

    static getLicenseUsers = asyncHandler(async (req, res) => {
        const license = License.getById(parseInt(req.params.id));
        if (!license) return res.status(404).json({ status: 'error', message: 'Lizenz nicht gefunden' });
        if (!license.sku_id) return res.json({ status: 'success', data: [] });

        const { getEntraLicenseUsers } = require('../services/graph.service');
        const users = await getEntraLicenseUsers(license.sku_id);
        res.json({ status: 'success', data: users });
    });
}

module.exports = LicenseController;
