#!/usr/bin/env node
/**
 * PR-1 Freeze Architecture Test
 * 
 * Run: node --test test/architecture/freeze.test.mjs
 * 
 * Tests:
 *   1. architecture-freeze-v2.md exists
 *   2. Document contains core/adapter/legacy/experimental sections
 *   3. Document contains 90-day legacy policy
 *   4. check-deprecations output includes replacement info
 *   5. check-deprecations output includes migration window
 *   6. production-check still passes
 *   7. guard still passes
 *   8. baseline still passes
 */

import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { execSync, spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";

const __dirname = join(fileURLToPath(import.meta.url), "..", "..", "..");
const ROOT = __dirname;
const SCRIPTS = join(ROOT, "scripts");
const DOCS = join(ROOT, "docs");

// ─── Helpers ──────────────────────────────────────────

function getFileSize(path) {
  try { return statSync(path).size; } catch { return 0; }
}

describe("PR-1: Freeze Architecture", () => {
  
  // ─── Test 1 ──────────────────────────────────────────
  it("architecture-freeze-v2.md exists and is non-empty", () => {
    const path = join(DOCS, "architecture-freeze-v2.md");
    assert.ok(existsSync(path), `Missing: ${path}`);
    const size = getFileSize(path);
    assert.ok(size > 1000, `File too small: ${size} bytes (expected >1000)`);
  });

  // ─── Test 2 ──────────────────────────────────────────
  it("document contains core / adapter / legacy / experimental sections", () => {
    const content = readFileSync(join(DOCS, "architecture-freeze-v2.md"), "utf8");
    
    const required = [
      "Core Module",
      "Adapter Module",
      "Legacy Module",
      "Experimental Module",
    ];
    
    for (const section of required) {
      assert.ok(content.includes(section),
        `Missing section: "${section}"`);
    }
  });

  // ─── Test 3 ──────────────────────────────────────────
  it("document contains 90-day legacy migration policy", () => {
    const content = readFileSync(join(DOCS, "architecture-freeze-v2.md"), "utf8");
    
    assert.ok(content.includes("90-day") || content.includes("90-Day") ||
      content.includes("90 day") || content.includes("Migration Window"),
      "Missing 90-day migration policy reference");
    
    assert.ok(content.includes("2026-09-04"),
      "Missing removal target date 2026-09-04");
  });

  // ─── Test 4 ──────────────────────────────────────────
  it("check-deprecations output includes replacement info", { timeout: 30000 }, () => {
    const result = spawnSync("node", [join(SCRIPTS, "check-deprecations.mjs")], {
      cwd: ROOT,
      encoding: "utf8",
      timeout: 25000,
      maxBuffer: 1024 * 1024,
    });
    
    const output = result.stdout + result.stderr;
    console.log(output.slice(-1000));
    
    // Deprecation check always exits 0 (never blocks on deprecation count)
    assert.equal(result.status, 0, `Script crashed (exit ${result.status})`);
    
    // Must contain replacement info in enhanced output
    assert.ok(
      output.includes("Replacement:") || output.includes("replacement"),
      "Missing replacement info in deprecation output"
    );
  });

  // ─── Test 5 ──────────────────────────────────────────
  it("check-deprecations output includes migration window", { timeout: 30000 }, () => {
    const result = spawnSync("node", [join(SCRIPTS, "check-deprecations.mjs")], {
      cwd: ROOT,
      encoding: "utf8",
      timeout: 25000,
      maxBuffer: 1024 * 1024,
    });
    
    const output = result.stdout + result.stderr;
    
    // Must contain migration window
    assert.ok(
      output.includes("Migration Window") || output.includes("migrationWindow") ||
      output.includes("Migration Timeline") || output.includes("Removal Target"),
      "Missing migration window info in deprecation output"
    );
  });

  // ─── Test 6 ──────────────────────────────────────────
  it("production-check still passes after freeze", { timeout: 120000 }, () => {
    const result = spawnSync("bash", [join(SCRIPTS, "production-check.sh")], {
      cwd: ROOT,
      encoding: "utf8",
      timeout: 110000,
      maxBuffer: 2 * 1024 * 1024,
    });
    
    const output = result.stdout + result.stderr;
    console.log(output.slice(-800));
    
    assert.equal(result.status, 0,
      `Production check failed after freeze (exit ${result.status}):\n${output.slice(-500)}`);
    assert.ok(output.includes("PRODUCTION CHECK PASSED") ||
      output.includes("Overall:"),
      "Production check summary not found");
  });

  // ─── Test 7 ──────────────────────────────────────────
  it("architecture guard still passes after freeze", { timeout: 60000 }, () => {
    const result = spawnSync("bash", [join(SCRIPTS, "guard-all.sh")], {
      cwd: ROOT,
      encoding: "utf8",
      timeout: 55000,
      maxBuffer: 1024 * 1024,
    });
    
    const output = result.stdout + result.stderr;
    console.log(output.slice(-500));
    
    assert.equal(result.status, 0,
      `Guard failed after freeze (exit ${result.status}):\n${output.slice(-300)}`);
  });

  // ─── Test 8 ──────────────────────────────────────────
  it("baseline tests still pass after freeze", { timeout: 60000 }, () => {
    const result = spawnSync("node", ["--test", "test/baseline/test-*.test.mjs"], {
      cwd: ROOT,
      encoding: "utf8",
      timeout: 55000,
      maxBuffer: 2 * 1024 * 1024,
      shell: true,
    });
    
    const output = result.stdout + result.stderr;
    
    assert.equal(result.status, 0,
      `Baseline tests failed after freeze (exit ${result.status})`);
    assert.ok(output.includes("fail 0") || !output.includes("fail"),
      "Baseline tests have failures");
  });
});
