import { expect, test } from "bun:test";
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";

const root = join(import.meta.dir, "..");
const authPackageRoot = join(root, "..", "..", "packages", "auth");

function read(...parts: string[]): string {
  return readFileSync(join(...parts), "utf8");
}

test("auth showcase contains registration, login, recovery, and protected account pages", () => {
  for (const page of [
    "index.wrn",
    "sign-in.wrn",
    "sign-up.wrn",
    "recover.wrn",
    "account.wrn",
    "otp.wrn",
    "magic-link.wrn",
    "two-factor.wrn",
    "authenticator.wrn",
    "invitation.wrn",
    "impersonation.wrn",
  ]) {
    expect(existsSync(join(root, "app", "pages", page))).toBe(true);
  }

  const account = read(root, "app", "pages", "account.wrn");
  const signIn = read(root, "app", "pages", "sign-in.wrn");
  expect(account).toContain("PasskeyButton");
  expect(account).toContain("AccountStatus");
  expect(account).toContain('action="/api/auth/logout"');
  expect(account).toContain('data-schema="auth-empty"');
  expect(signIn).toContain("<Captcha");
  expect(signIn).toContain('action="auth-login"');
  expect(signIn).toContain('required="true"');
  expect(signIn).toContain('resetOnError="false"');
  expect(existsSync(join(root, "app", "middleware", "captcha-login.ts"))).toBe(true);
  expect(existsSync(join(root, "app", "api", "captcha", "[...path].ts"))).toBe(true);
  expect(read(root, "app", "middleware", "captcha-login.ts")).toContain(
    "verifiedForMs: 5 * 60_000",
  );
});

test("auth showcase uses package-owned routes and advanced components", () => {
  const auth = read(root, "app", "lib", "auth.ts");
  const config = read(root, "wrnexus.config.ts");

  expect(auth).toContain("createAuthEngine");
  expect(auth).toContain("onSignedIn");
  expect(auth).toContain("onSignedOut");
  expect(auth).toContain("onSuccessfulSignUp");
  expect(auth).toContain("autoSignIn: true");
  expect(config).toContain("engine: auth");
  expect(config).toContain("routes: true");
  expect(config).toContain("migrations: false");
  expect(config).not.toContain("onSignedIn");
  expect(config).not.toContain("onSignedOut");

  expect(existsSync(join(root, "app", "api", "auth", "register.ts"))).toBe(false);
  expect(existsSync(join(root, "app", "schemas", "auth-register.ts"))).toBe(false);

  expect(read(root, "app", "pages", "otp.wrn")).toContain("OtpSignIn");
  expect(read(root, "app", "pages", "magic-link.wrn")).toContain("MagicLinkSignIn");
  expect(read(root, "app", "pages", "impersonation.wrn")).toContain("ImpersonationBanner");
});

test("package auth schemas are shared by browser forms and API handlers", () => {
  const validation = read(authPackageRoot, "src", "validation.ts");
  const plugin = read(authPackageRoot, "src", "plugin.ts");
  const handlers = read(authPackageRoot, "src", "http", "index.ts");
  const signUp = read(authPackageRoot, "components", "SignUp.wrn");
  const forgotPassword = read(authPackageRoot, "components", "ForgotPassword.wrn");

  expect(validation).toContain("export const signUpSchema");
  expect(validation).toContain("export const authSchemas");
  expect(validation).toContain("export const authBrowserSchemaMap");

  expect(plugin).toContain("authBrowserSchemaDescriptors");
  expect(plugin).toContain("setDefaultAuthEngine(value.engine)");

  expect(handlers).toContain("parseBody(schemas.register, ctx.req)");
  expect(handlers).toContain("parseBody(schemas.passwordResetRequest, ctx.req)");

  expect(signUp).toContain('schema = "auth-register"');
  expect(signUp).toContain("data-schema='{schema}'");
  expect(signUp).toContain("novalidate");

  expect(forgotPassword).toContain('schema = "auth-password-request"');
  expect(forgotPassword).toContain("data-schema='{schema}'");
  expect(forgotPassword).toContain("novalidate");
});

test("authz is wired with a real declaration and a registered middleware, not a dangling file", () => {
  expect(existsSync(join(root, "app", "authz", "showcase.ts"))).toBe(true);
  expect(existsSync(join(root, "app", "middleware", "authz.ts"))).toBe(true);

  const declaration = read(root, "app", "authz", "showcase.ts");
  expect(declaration).toContain("defineAuthz");
  expect(declaration).toContain('"post:read": { title: "View posts", public: true }');
  expect(declaration).toContain("bindings:");

  const middleware = read(root, "app", "middleware", "authz.ts");
  expect(middleware).toContain("authzMiddleware");
  expect(middleware).toContain("getAuthzCatalog()");
  expect(middleware).toContain("memoryPermissionStore()");

  const manifest = JSON.parse(read(root, "package.json")) as {
    dependencies?: Record<string, string>;
  };
  expect(manifest.dependencies?.["@wrnexus/authz"]).toBe("workspace:*");
});
