const { getDatabase } = require('../config/database');
const { asyncHandler } = require('../middleware/errorHandler');

// Validate X-Scanner-Key header
const validateScannerKey = (req, res) => {
    const key = req.headers['x-scanner-key'];
    if (!key || key !== process.env.SCANNER_API_KEY) {
        res.status(401).json({ status: 'error', message: 'Invalid scanner key' });
        return false;
    }
    return true;
};

// POST /api/scanner/assets  — called by nexus-scanner (no JWT)
const reportAssets = asyncHandler(async (req, res) => {
    if (!validateScannerKey(req, res)) return;

    const { site, scanner_version, reported_at, assets } = req.body;
    if (!site || !Array.isArray(assets)) {
        return res.status(400).json({ status: 'error', message: 'site and assets[] required' });
    }

    const db = getDatabase();
    const now = new Date().toISOString();

    // Upsert scanner site
    db.prepare(`
        INSERT INTO scanner_sites (site_id, last_seen, scanner_version, host_count)
        VALUES (?, ?, ?, ?)
        ON CONFLICT(site_id) DO UPDATE SET
            last_seen = excluded.last_seen,
            scanner_version = excluded.scanner_version,
            host_count = excluded.host_count
    `).run(site, now, scanner_version || '1.0', assets.length);

    // Upsert each asset
    const upsert = db.prepare(`
        INSERT INTO scanner_assets (site_id, ip, mac, hostname, vendor, status, first_seen, last_seen, updated_at)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ON CONFLICT(site_id, ip) DO UPDATE SET
            mac       = excluded.mac,
            hostname  = CASE WHEN excluded.hostname != '' THEN excluded.hostname ELSE hostname END,
            vendor    = CASE WHEN excluded.vendor != '' THEN excluded.vendor ELSE vendor END,
            status    = excluded.status,
            last_seen = excluded.last_seen,
            updated_at = excluded.updated_at
    `);

    const insertMany = db.transaction((items) => {
        for (const a of items) {
            upsert.run(
                site,
                a.ip,
                a.mac || '',
                a.hostname || '',
                a.vendor || '',
                a.status || 'online',
                a.first_seen || now,
                a.last_seen || now,
                now
            );
        }
    });

    insertMany(assets);

    res.json({ status: 'success', received: assets.length });
});

// POST /api/scanner/alert  — called by nexus-scanner (no JWT)
const reportAlert = asyncHandler(async (req, res) => {
    if (!validateScannerKey(req, res)) return;

    const { site, check, type, target, status, latency, error, subject } = req.body;
    if (!site || !check || !status) {
        return res.status(400).json({ status: 'error', message: 'site, check, status required' });
    }

    const db = getDatabase();

    db.prepare(`
        INSERT INTO scanner_alerts (site_id, check_name, check_type, target, status, latency_ms, error_msg, subject)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(site, check, type || '', target || '', status, latency || 0, error || '', subject || '');

    // Update check_count on site
    db.prepare(`UPDATE scanner_sites SET check_count = check_count + 1 WHERE site_id = ?`).run(site);

    res.json({ status: 'success' });
});

// GET /api/scanner/sites  — JWT required
const getSites = asyncHandler(async (req, res) => {
    const db = getDatabase();
    const sites = db.prepare(`SELECT * FROM scanner_sites ORDER BY site_id`).all();
    res.json({ status: 'success', data: sites });
});

// GET /api/scanner/assets  — JWT required
const getAssets = asyncHandler(async (req, res) => {
    const db = getDatabase();
    const { site, status, q } = req.query;

    let query = `SELECT * FROM scanner_assets WHERE 1=1`;
    const params = [];

    if (site) { query += ` AND site_id = ?`; params.push(site); }
    if (status) { query += ` AND status = ?`; params.push(status); }
    if (q) {
        query += ` AND (ip LIKE ? OR hostname LIKE ? OR mac LIKE ? OR vendor LIKE ?)`;
        const like = `%${q}%`;
        params.push(like, like, like, like);
    }
    query += ` ORDER BY last_seen DESC LIMIT 500`;

    const assets = db.prepare(query).all(...params);
    res.json({ status: 'success', data: assets });
});

// GET /api/scanner/alerts  — JWT required
const getAlerts = asyncHandler(async (req, res) => {
    const db = getDatabase();
    const { site, limit = 100 } = req.query;

    let query = `SELECT * FROM scanner_alerts WHERE 1=1`;
    const params = [];

    if (site) { query += ` AND site_id = ?`; params.push(site); }
    query += ` ORDER BY triggered_at DESC LIMIT ?`;
    params.push(Number(limit));

    const alerts = db.prepare(query).all(...params);
    res.json({ status: 'success', data: alerts });
});

// GET /api/scanner/stats  — JWT required, summary numbers
const getStats = asyncHandler(async (req, res) => {
    const db = getDatabase();
    const sites = db.prepare(`SELECT COUNT(*) as cnt FROM scanner_sites`).get().cnt;
    const total = db.prepare(`SELECT COUNT(*) as cnt FROM scanner_assets`).get().cnt;
    const online = db.prepare(`SELECT COUNT(*) as cnt FROM scanner_assets WHERE status='online'`).get().cnt;
    const alerts24h = db.prepare(`
        SELECT COUNT(*) as cnt FROM scanner_alerts
        WHERE triggered_at >= datetime('now','-24 hours') AND status='offline'
    `).get().cnt;

    res.json({ status: 'success', data: { sites, total, online, offline: total - online, alerts24h } });
});

module.exports = { reportAssets, reportAlert, getSites, getAssets, getAlerts, getStats };
