/**
 * PR-A Baseline Test 08: Config Loading
 * Verifies: config loads correctly, invalid config is rejected
 * Freezes: config loading contract
 */

import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";

const CONFIG_PATH = join(homedir(), ".openclaw", "openclaw.json");
const TEMP_INVALID_CONFIG = join(homedir(), ".openclaw", "openclaw-invalid-test.json");

describe("test-08: Config Loading Baseline", () => {
  it("08.01 - config file exists and is valid JSON", () => {
    assert.ok(existsSync(CONFIG_PATH), "openclaw.json must exist");
    const content = readFileSync(CONFIG_PATH, "utf8");
    let parsed;
    try {
      parsed = JSON.parse(content);
    } catch (e) {
      assert.fail(`config must be valid JSON: ${e.message}`);
    }
    console.log("[BASELINE] config top-level keys:", Object.keys(parsed).join(", "));
    assert.ok(typeof parsed === "object", "config must be object");
  });

  it("08.02 - config sections recorded", () => {
    const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
    const sections = {
      gateway: !!config.gateway,
      agents: !!config.agents,
      models: !!config.models,
      plugins: !!config.plugins,
      channels: !!config.channels,
      tools: !!config.tools,
      diagnostics: !!config.diagnostics,
    };
    console.log("[BASELINE] config sections present:", JSON.stringify(sections));
    assert.ok(sections.gateway, "gateway section must exist");
    assert.ok(sections.models, "models section should exist");
  });

  it("08.03 - config validate CLI works", () => {
    const out = execSync("openclaw config get gateway 2>&1", {
      timeout: 10000,
      encoding: "utf8",
    }).trim();
    console.log("[BASELINE] config get gateway:", out.substring(0, 200));
    // Should not error
    assert.ok(!out.toLowerCase().includes("error") || out.includes("Error"),
      "config get must return data or clear error");
  });

  it("08.04 - invalid JSON config is rejected", () => {
    // Create a temporary invalid config for testing rejection behavior
    const invalidContent = "{ this is not valid json {{{";
    try {
      // Don't actually create it on the real config path
      // Instead use openclaw config validate with a test file
      writeFileSync(TEMP_INVALID_CONFIG, invalidContent, "utf8");
      
      // Test that openclaw rejects it
      try {
        execSync(`OPENCLAW_CONFIG_PATH="${TEMP_INVALID_CONFIG}" openclaw config get gateway 2>&1`, {
          timeout: 10000,
          encoding: "utf8",
        });
      } catch (e) {
        console.log("[BASELINE] invalid config rejection:", e.stderr?.substring(0, 200) || e.message?.substring(0, 200));
        // Error on invalid config is expected behavior
        assert.ok(e.stderr || e.message, "invalid config must produce error");
      }
    } finally {
      try { unlinkSync(TEMP_INVALID_CONFIG); } catch {}
    }
  });

  it("08.05 - config with unknown keys loads without crash", () => {
    const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
    // Check if unknown keys cause silent failure
    // In practice, extra keys should be silently ignored or warned
    console.log("[BASELINE] config key count:", Object.keys(config).length);
    assert.ok(Object.keys(config).length > 0, "config must have sections");
  });

  it("08.06 - config dot-path get works", () => {
    const paths = [
      "gateway.bind",
      "gateway.auth.mode",
      "gateway.port",
    ];
    for (const p of paths) {
      try {
        const out = execSync(`openclaw config get "${p}" 2>&1`, {
          timeout: 10000,
          encoding: "utf8",
        }).trim();
        console.log(`[BASELINE] config get ${p}:`, out.substring(0, 100));
      } catch (e) {
        console.log(`[BASELINE] config get ${p}: not found or error`);
      }
    }
    assert.ok(true, "baseline frozen: dot-path get");
  });
});
