import { readFileSync, readdirSync, statSync } from "fs";
import path from "path";

import { describe, expect, it } from "vitest";

const ROOT = process.cwd();

function walk(dir: string, filter: (file: string) => boolean): string[] {
  const absolute = path.join(ROOT, dir);
  const results: string[] = [];
  let entries: string[];
  try {
    entries = readdirSync(absolute);
  } catch {
    return results;
  }
  for (const entry of entries) {
    if (entry === "node_modules" || entry === ".next") continue;
    const full = path.join(absolute, entry);
    const rel = path.relative(ROOT, full);
    if (statSync(full).isDirectory()) {
      results.push(...walk(rel, filter));
    } else if (filter(full)) {
      results.push(rel);
    }
  }
  return results;
}

const read = (rel: string) => readFileSync(path.join(ROOT, rel), "utf8");
const isSource = (file: string) => /\.(ts|tsx)$/.test(file) && !file.endsWith(".d.ts");

const componentFiles = walk("components", isSource);
const appFiles = walk("app", isSource);
const libFiles = walk("lib", isSource);
const actionFiles = [...appFiles].filter((file) => /(^|\/)actions\.tsx?$/.test(file));

describe("architecture: data access boundaries", () => {
  it("no component imports the Prisma client", () => {
    const offenders = componentFiles.filter((file) => /["']@\/lib\/prisma["']/.test(read(file)));
    expect(offenders).toEqual([]);
  });

  it("no client component imports the Prisma client (defense in depth)", () => {
    const offenders = [...componentFiles, ...appFiles].filter((file) => {
      const source = read(file);
      return /["']use client["']/.test(source) && /lib\/prisma/.test(source);
    });
    expect(offenders).toEqual([]);
  });

  it("code imports admin server actions from the canonical _admin source, never the mirrors", () => {
    const offenders = [...componentFiles, ...appFiles, ...libFiles].filter((file) =>
      /from\s+["']@\/app\/(root|admin-internal)\//.test(read(file)),
    );
    expect(offenders).toEqual([]);
  });

  it("lib modules never import from the app layer", () => {
    const offenders = libFiles.filter((file) => {
      const source = read(file);
      return /from\s+["']@\/app\//.test(source) || /from\s+["']\.\.\/app\//.test(source);
    });
    expect(offenders).toEqual([]);
  });
});

describe("architecture: server actions", () => {
  it("finds the expected server action files", () => {
    expect(actionFiles.length).toBeGreaterThan(0);
  });

  it('every actions file starts with the "use server" directive', () => {
    for (const file of actionFiles) {
      const firstMeaningfulLine = read(file)
        .split("\n")
        .map((line) => line.trim())
        .find((line) => line.length > 0);
      expect(firstMeaningfulLine, file).toMatch(/^["']use server["'];?$/);
    }
  });

  it("every admin action file enforces authentication", () => {
    const adminActionFiles = actionFiles.filter((file) => file.includes(`${path.sep}_admin${path.sep}`));
    expect(adminActionFiles.length).toBeGreaterThan(0);
    for (const file of adminActionFiles) {
      const source = read(file);
      expect(
        /ensureAdmin\s*\(/.test(source) ||
          /requireAdminAuth\s*\(/.test(source) ||
          /isAdminAuthenticated\s*\(/.test(source),
        file,
      ).toBe(true);
    }
  });
});

describe("architecture: admin mirror parity", () => {
  const canonicalPages = walk("app/_admin", (file) => /page\.tsx$/.test(file));

  it("has admin pages to mirror", () => {
    expect(canonicalPages.length).toBeGreaterThan(0);
  });

  for (const mirror of ["root", "admin-internal"]) {
    it(`mirrors every _admin page under app/${mirror} via a re-export`, () => {
      const missing: string[] = [];
      for (const page of canonicalPages) {
        const mirrored = page.replace(`app${path.sep}_admin${path.sep}`, `app${path.sep}${mirror}${path.sep}`);
        try {
          const source = read(mirrored);
          if (!source.includes("_admin")) {
            missing.push(`${mirrored} (does not re-export _admin)`);
          }
        } catch {
          missing.push(`${mirrored} (missing)`);
        }
      }
      expect(missing).toEqual([]);
    });
  }
});
