/**
 * Testet die Sammelaktionen der Seitenleiste ohne Browser.
 *
 * Die Methoden werden aus app.js herausgeloest und gegen ein schlankes
 * DOM-Double laufen gelassen. Kein Netzzugriff, keine Kosten.
 *
 * Aufruf aus dem Projektstamm:
 *     node tests/test_sammelaktionen.js
 */
'use strict';

const fs = require('fs');
const path = require('path');
const vm = require('vm');

let ok = 0;
let fail = 0;

function pruefe(name, bedingung, extra) {
    if (bedingung) {
        ok++;
        console.log('  OK    ' + name);
    } else {
        fail++;
        console.log('  FEHL  ' + name + ' '
            + (extra === undefined ? '' : JSON.stringify(extra)));
    }
}

// --- DOM-Double, nur was die Sammelaktionen anfassen ---
function element(id) {
    return {
        id: id,
        hidden: false,
        checked: false,
        textContent: '',
        style: {},
        _span: { textContent: '' },
        querySelector(sel) { return sel === 'span' ? this._span : null; },
    };
}

const elemente = {};
for (const id of ['sidebar-bulk-tools', 'sidebar-bulk-bar', 'sidebar-bulk-count',
                  'sidebar-bulk-all', 'sidebar-bulk-archive', 'sidebar-bulk-activate',
                  'sidebar-bulk-delete', 'empty-state', 'incident-view']) {
    elemente[id] = element(id);
}

const meldungen = [];
const aufrufe = { update: [], delete: [] };

const umgebung = {
    document: { getElementById: (id) => elemente[id] || null },
    UI: { showToast: (text, art) => meldungen.push({ text, art }) },
    API: {
        updateIncident: async (id, daten) => { aufrufe.update.push({ id, daten }); },
        deleteIncident: async (id) => { aufrufe.delete.push(id); },
    },
    confirm: () => umgebung._bestaetigen,
    _bestaetigen: true,
    console: console,
};
umgebung.window = umgebung;

// --- Die Sammelaktionen aus app.js herausloesen ---
const quelle = fs.readFileSync(
    path.join(__dirname, '..', 'src', 'static', 'js', 'app.js'), 'utf8');
const von = quelle.indexOf('    // === Sammelaktionen in der Seitenleiste ===');
const bis = quelle.indexOf('    renderSidebar() {', von);
if (von === -1 || bis === -1) {
    console.log('FEHLER: Sammelaktionen in app.js nicht gefunden');
    process.exit(1);
}

const kontext = vm.createContext(umgebung);
vm.runInContext('var App = {\n' + quelle.slice(von, bis) + '\n'
    + '  incidents: [], currentIncidentId: null, _sidebarFilter: "all",'
    + ' _currentUsername: "ich",\n'
    + '  renderSidebar() { this._renderBulkBar(); },\n'
    + '  async loadIncidents() { this._geladen = (this._geladen || 0) + 1; },\n'
    + '};', kontext);
const App = kontext.App;

const LAGEN = [
    { id: 1, title: 'Ceuta', status: 'active', article_count: 40, created_by_username: 'ich' },
    { id: 2, title: 'IMK 2026', status: 'active', article_count: 20, created_by_username: 'wer' },
    { id: 3, title: 'Altfall', status: 'archived', article_count: 5, created_by_username: 'ich' },
];

function neu() {
    App.incidents = LAGEN.map(l => Object.assign({}, l));
    App._bulkMode = null;
    App._bulkSel = new Set();
    App._sidebarFilter = 'all';
    App.currentIncidentId = null;
    aufrufe.update.length = 0;
    aufrufe.delete.length = 0;
    meldungen.length = 0;
    umgebung._bestaetigen = true;
    for (const el of Object.values(elemente)) {
        el.hidden = false;
        el.checked = false;
        el.textContent = '';
        el.style = {};
        el._span.textContent = '';
    }
}

async function main() {
    console.log('\nA) Der Auswahlmodus schaltet die Leisten um');
    neu();
    pruefe('A1 normal ist der Auswahlmodus aus', App._bulkMode === null);
    App.startBulkMode('archive');
    pruefe('A2 Startleiste verschwindet', elemente['sidebar-bulk-tools'].hidden === true);
    pruefe('A3 Bestaetigungsleiste erscheint', elemente['sidebar-bulk-bar'].hidden === false);
    pruefe('A4 Hinweis fordert zum Anhaken auf',
           elemente['sidebar-bulk-count'].textContent.includes('anhaken'),
           elemente['sidebar-bulk-count'].textContent);
    App.endBulkMode();
    pruefe('A5 Abbrechen stellt den Ausgangszustand her',
           App._bulkMode === null && elemente['sidebar-bulk-tools'].hidden === false);
    pruefe('A6 Auswahl wird dabei verworfen', App._bulkSel.size === 0);

    console.log('\nB) Angeboten wird nur, was zur Auswahl passt');
    neu();
    App.startBulkMode('archive');
    App.toggleBulkSel(1, true);
    pruefe('B1 Archivieren sichtbar bei aktiver Lage',
           elemente['sidebar-bulk-archive'].hidden === false);
    pruefe('B2 Aktivieren verborgen ohne archivierte Lage',
           elemente['sidebar-bulk-activate'].hidden === true);
    pruefe('B3 Loeschen im Archivmodus verborgen',
           elemente['sidebar-bulk-delete'].hidden === true);
    pruefe('B4 Zaehler im Knopf stimmt',
           elemente['sidebar-bulk-archive']._span.textContent === 'Archivieren (1)',
           elemente['sidebar-bulk-archive']._span.textContent);
    App.toggleBulkSel(3, true);
    pruefe('B5 Aktivieren erscheint bei archivierter Lage',
           elemente['sidebar-bulk-activate'].hidden === false);
    pruefe('B6 beide Zaehler stimmen',
           elemente['sidebar-bulk-archive']._span.textContent === 'Archivieren (1)'
           && elemente['sidebar-bulk-activate']._span.textContent === 'Aktivieren (1)');
    pruefe('B7 Auswahl wird gezaehlt',
           elemente['sidebar-bulk-count'].textContent === '2 Lagen ausgewählt',
           elemente['sidebar-bulk-count'].textContent);
    neu();
    App.startBulkMode('delete');
    App.toggleBulkSel(1, true);
    pruefe('B8 im Loeschmodus nur Loeschen',
           elemente['sidebar-bulk-delete'].hidden === false
           && elemente['sidebar-bulk-archive'].hidden === true);
    pruefe('B9 Zaehler im Loeschknopf',
           elemente['sidebar-bulk-delete']._span.textContent === 'Löschen (1)',
           elemente['sidebar-bulk-delete']._span.textContent);

    console.log('\nC) Alle sichtbaren auswaehlen achtet auf den Filter');
    neu();
    App.startBulkMode('archive');
    App.selectAllVisible(true);
    pruefe('C1 ohne Filter sind alle drei gewaehlt', App._bulkSel.size === 3, App._bulkSel.size);
    pruefe('C2 der Alle-Haken spiegelt das', elemente['sidebar-bulk-all'].checked === true);
    App.selectAllVisible(false);
    pruefe('C3 abwaehlen leert die Auswahl', App._bulkSel.size === 0);
    App._sidebarFilter = 'mine';
    App.selectAllVisible(true);
    pruefe('C4 mit Filter nur die eigenen', App._bulkSel.size === 2, [...App._bulkSel]);
    pruefe('C5 der fremde Fall fehlt', !App._bulkSel.has(2));

    console.log('\nD) Archivieren wirkt nur auf aktive Lagen');
    neu();
    App.startBulkMode('archive');
    App._bulkSel = new Set([1, 3]);
    await App.bulkStatus('archived');
    pruefe('D1 nur die aktive Lage wurde archiviert',
           aufrufe.update.length === 1 && aufrufe.update[0].id === 1, aufrufe.update);
    pruefe('D2 Status korrekt gesetzt',
           aufrufe.update[0].daten.status === 'archived', aufrufe.update[0]);
    pruefe('D3 Auswahlmodus endet danach', App._bulkMode === null);
    pruefe('D4 Rueckmeldung an den Nutzer',
           meldungen.length === 1 && meldungen[0].art === 'success', meldungen);

    console.log('\nE) Aktivieren wirkt nur auf archivierte Lagen');
    neu();
    App.startBulkMode('archive');
    App._bulkSel = new Set([1, 3]);
    await App.bulkStatus('active');
    pruefe('E1 nur die archivierte Lage wurde aktiviert',
           aufrufe.update.length === 1 && aufrufe.update[0].id === 3, aufrufe.update);

    console.log('\nF) Loeschen fragt nach und raeumt auf');
    neu();
    App.startBulkMode('delete');
    App._bulkSel = new Set([1, 2]);
    umgebung._bestaetigen = false;
    await App.bulkDelete();
    pruefe('F1 ohne Bestaetigung wird nichts geloescht', aufrufe.delete.length === 0);
    pruefe('F2 der Auswahlmodus bleibt bestehen', App._bulkMode === 'delete');

    umgebung._bestaetigen = true;
    App.currentIncidentId = 1;
    await App.bulkDelete();
    pruefe('F3 beide Lagen geloescht',
           aufrufe.delete.length === 2 && aufrufe.delete.includes(1), aufrufe.delete);
    pruefe('F4 die offene Lage wird geschlossen', App.currentIncidentId === null);
    pruefe('F5 die Leeransicht erscheint',
           elemente['empty-state'].style.display === 'flex'
           && elemente['incident-view'].style.display === 'none',
           [elemente['empty-state'].style.display, elemente['incident-view'].style.display]);

    console.log('\nG) Fehlschlaege werden gemeldet statt verschluckt');
    neu();
    App.startBulkMode('archive');
    App._bulkSel = new Set([1]);
    const alteFunktion = umgebung.API.updateIncident;
    umgebung.API.updateIncident = async () => { throw new Error('kein Recht'); };
    await App.bulkStatus('archived');
    umgebung.API.updateIncident = alteFunktion;
    pruefe('G1 Fehlermeldung erscheint',
           meldungen.length === 1 && meldungen[0].art === 'error', meldungen);
    pruefe('G2 die betroffene Nummer steht darin',
           meldungen[0].text.includes('1'), meldungen[0].text);

    console.log('\nH) Leere Auswahl loest nichts aus');
    neu();
    App.startBulkMode('archive');
    await App.bulkStatus('archived');
    await App.bulkDelete();
    pruefe('H1 keine Aufrufe ohne Auswahl',
           aufrufe.update.length === 0 && aufrufe.delete.length === 0);
    pruefe('H2 keine Rueckmeldung ohne Auswahl', meldungen.length === 0, meldungen);

    console.log('\nErgebnis: ' + ok + ' bestanden, ' + fail + ' fehlgeschlagen');
    process.exit(fail ? 1 : 0);
}

main();
