/**
 * L1 architecture guard: only `src/adapters` may import `@tauri-apps/api` or
 * call `invoke()`. React components (features/app) must go through the gateway
 * ports (ARCHITECTURE §1.3, L1 DoD "Aucun invoke() direct dans les composants").
 */
import { describe, it, expect } from "vitest";
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join, sep } from "node:path";

// Vitest runs with cwd = frontend/; scan the whole `src` tree from there.
const SRC = join(process.cwd(), "src");

/** Recursively collect .ts/.tsx files, skipping the allowed adapters dir. */
function collectSourceFiles(dir: string, out: string[] = []): string[] {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    if (statSync(full).isDirectory()) {
      // `src/adapters` is the single allowed home of Tauri transport code.
      if (full.endsWith(`${sep}adapters`)) continue;
      collectSourceFiles(full, out);
    } else if (/\.tsx?$/.test(entry) && !/\.test\.tsx?$/.test(entry)) {
      out.push(full);
    }
  }
  return out;
}

/** Strips block and line comments so doc-comment mentions don't false-positive. */
function stripComments(src: string): string {
  return src
    .replace(/\/\*[\s\S]*?\*\//g, "")
    .replace(/\/\/[^\n]*/g, "");
}

describe("no direct Tauri usage outside src/adapters", () => {
  const files = collectSourceFiles(SRC);

  it("finds source files to scan", () => {
    expect(files.length).toBeGreaterThan(0);
  });

  it("no file imports @tauri-apps/api", () => {
    const offenders = files.filter((f) =>
      stripComments(readFileSync(f, "utf8")).includes("@tauri-apps/api"),
    );
    expect(offenders, `offending files: ${offenders.join(", ")}`).toEqual([]);
  });

  it("no file calls invoke( (ignoring comments)", () => {
    const offenders = files.filter((f) =>
      /\binvoke\s*\(/.test(stripComments(readFileSync(f, "utf8"))),
    );
    expect(offenders, `offending files: ${offenders.join(", ")}`).toEqual([]);
  });
});
