// @vitest-environment node
/**
 * Öffnen und Anzeigen geschriebener Dateien.
 *
 * **Der Anlass.** Alle Druckausgaben und die Sicherung endeten bis 0.22.0 mit
 * einem reinen Textsatz samt Pfad. Wer die eben erzeugte Fragenliste drucken
 * oder die Sicherung auf einen Stick ziehen wollte, musste den Pfad ablesen
 * und im Explorer selbst hinnavigieren.
 *
 * **Was hier vor allem geprüft wird**, ist die Wache: `shell.openPath`
 * überlässt dem Betriebssystem, womit eine Datei geöffnet wird. Käme der Pfad
 * aus dem Renderer, wäre das ein Weg, beliebige Dateien starten zu lassen –
 * dieselbe Überlegung, aus der die Sicherung nur Kennungen und nie Pfade über
 * die Brücke schickt.
 */

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const geoeffnet: string[] = [];
const gezeigt: string[] = [];
let oeffnenFehler = '';

vi.mock('electron', () => ({
  shell: {
    openPath: (pfad: string): Promise<string> => {
      geoeffnet.push(pfad);
      return Promise.resolve(oeffnenFehler);
    },
    showItemInFolder: (pfad: string): void => {
      gezeigt.push(pfad);
    },
  },
}));

const { dateiZeigen, geschriebenMerken, geschriebeneVergessen } =
  await import('../src/main/dateizugriff');

beforeEach(() => {
  geoeffnet.length = 0;
  gezeigt.length = 0;
  oeffnenFehler = '';
  geschriebeneVergessen();
});

afterEach(() => {
  geschriebeneVergessen();
});

describe('Nur, was diese Anwendung selbst geschrieben hat', () => {
  it('öffnet eine gemerkte Datei', async () => {
    const kennung = geschriebenMerken('C:/Users/Erika/Dokumente/Lernbericht.pdf');

    await expect(dateiZeigen(kennung, 'oeffnen')).resolves.toBe(true);
    expect(geoeffnet).toEqual(['C:/Users/Erika/Dokumente/Lernbericht.pdf']);
  });

  it('zeigt eine gemerkte Datei im Ordner', async () => {
    const kennung = geschriebenMerken('C:/Users/Erika/Dokumente/Sicherung.wsklernstand');

    await expect(dateiZeigen(kennung, 'ordner')).resolves.toBe(true);
    expect(gezeigt).toEqual(['C:/Users/Erika/Dokumente/Sicherung.wsklernstand']);
  });

  it('öffnet nichts bei einer unbekannten Kennung', async () => {
    /* Der eigentliche Zweck der Merkliste: Eine erfundene Kennung darf
       nirgendwo hinführen. */
    await expect(dateiZeigen('datei-999', 'oeffnen')).resolves.toBe(false);
    expect(geoeffnet).toEqual([]);
  });

  it('nimmt keinen Pfad entgegen, auch wenn einer geschickt wird', async () => {
    /* Der Kanal nimmt Kennungen. Ein Pfad ist keine – und wird deshalb wie
       jede andere unbekannte Zeichenkette abgewiesen. */
    geschriebenMerken('C:/Users/Erika/Dokumente/Lernbericht.pdf');

    await expect(dateiZeigen('C:/Windows/System32/cmd.exe', 'oeffnen')).resolves.toBe(false);
    await expect(dateiZeigen('C:/Users/Erika/Dokumente/Lernbericht.pdf', 'oeffnen')).resolves.toBe(
      false,
    );
    expect(geoeffnet).toEqual([]);
  });

  it('weist alles ab, was keine Zeichenkette ist', async () => {
    for (const unfug of [null, undefined, 42, {}, []]) {
      await expect(dateiZeigen(unfug, 'oeffnen')).resolves.toBe(false);
    }
    expect(geoeffnet).toEqual([]);
  });

  it('vergibt für jede Datei eine eigene Kennung', async () => {
    const a = geschriebenMerken('C:/a.pdf');
    const b = geschriebenMerken('C:/b.pdf');

    expect(a).not.toBe(b);
    await dateiZeigen(a, 'oeffnen');
    expect(geoeffnet).toEqual(['C:/a.pdf']);
  });

  it('meldet, wenn das System die Datei nicht öffnen konnte', async () => {
    /* Etwa weil sie inzwischen verschoben wurde. Die Oberfläche sagt das
       dann, statt so zu tun, als sei etwas geschehen. */
    const kennung = geschriebenMerken('C:/weg.pdf');
    oeffnenFehler = 'Datei nicht gefunden';

    await expect(dateiZeigen(kennung, 'oeffnen')).resolves.toBe(false);
  });

  it('vergisst alles nach dem Zurücksetzen', async () => {
    /* Die Liste lebt nur im Arbeitsspeicher – nach einem Neustart führt ein
       alter Verweis nirgendwohin, und das ist richtig so. */
    const kennung = geschriebenMerken('C:/a.pdf');
    geschriebeneVergessen();

    await expect(dateiZeigen(kennung, 'oeffnen')).resolves.toBe(false);
  });
});
