import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import {
  existsSync,
  mkdtempSync,
  readFileSync,
  readdirSync,
  rmSync,
  writeFileSync,
} from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
  isLocalFallbackAuthorized,
  loadConfigResult,
  type ConfigLoadResult,
} from "./config";

describe("loadConfigResult", () => {
  let dir: string;

  beforeEach(() => {
    dir = mkdtempSync(join(tmpdir(), "controller-config-"));
  });

  afterEach(() => {
    rmSync(dir, { recursive: true, force: true });
    delete process.env.BUILD_REMOTE_LOCAL_FALLBACK;
  });

  test("missing config file is healthy with defaults", () => {
    const path = join(dir, "missing.toml");
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(false);
    expect(result.config.port).toBe(8787);
    expect(result.legitimatelyDisabled).toBe(false);
  });

  test("valid enabled:false is legitimately disabled", () => {
    const path = join(dir, "disabled.toml");
    writeFileSync(path, "enabled = false\n");
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(false);
    expect(result.legitimatelyDisabled).toBe(true);
    expect(isLocalFallbackAuthorized(result)).toBe(true);
  });

  test("invalid TOML is preserved and degrades with one incident", () => {
    const path = join(dir, "controller.toml");
    const corrupt = "port = [\n";
    writeFileSync(path, corrupt);
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(true);
    expect(result.incident?.kind).toBe("config-invalid-toml");
    expect(isLocalFallbackAuthorized(result)).toBe(false);
    expect(result.incident).toBeDefined();
    const preserved = readdirSync(dir).filter((name) =>
      /^controller\.toml\.invalid-\d+$/.test(name),
    );
    expect(preserved).toHaveLength(1);
    expect(readFileSync(join(dir, preserved[0]!), "utf8")).toBe(corrupt);
    expect(existsSync(path)).toBe(false);
  });

  test("invalid schema is preserved and never local fail-open", () => {
    const path = join(dir, "controller.toml");
    writeFileSync(path, 'port = "not-a-number"\n');
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(true);
    expect(result.incident?.kind).toBe("config-invalid-shape");
    expect(isLocalFallbackAuthorized(result)).toBe(false);
    expect(
      readdirSync(dir).filter((name) =>
        /^controller\.toml\.invalid-\d+$/.test(name),
      ),
    ).toHaveLength(1);
    expect(existsSync(path)).toBe(false);
  });

  test("non-loopback bindHost is invalid shape and falls back to literal loopback", () => {
    const path = join(dir, "controller.toml");
    writeFileSync(path, 'bindHost = "192.168.1.1"\n');
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(true);
    expect(result.incident?.kind).toBe("config-invalid-shape");
    expect(result.config.bindHost).toBe("127.0.0.1");
    expect(result.config.notify.mode).toBe("both");
  });

  test("defaults notify mode to both when section is absent", () => {
    const path = join(dir, "ok.toml");
    writeFileSync(path, "enabled = true\n");
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(false);
    expect(result.config.notify).toEqual({ mode: "both" });
  });

  test("invalid notify mode degrades with one config incident", () => {
    const path = join(dir, "controller.toml");
    writeFileSync(path, '[notify]\nmode = "pager"\n');
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(true);
    expect(result.incident?.kind).toBe("config-invalid-shape");
    expect(result.config.notify.mode).toBe("both");
  });

  test("BUILD_REMOTE_LOCAL_FALLBACK honored only when config valid", () => {
    const path = join(dir, "ok.toml");
    writeFileSync(path, "enabled = true\n");
    process.env.BUILD_REMOTE_LOCAL_FALLBACK = "1";
    const result = loadConfigResult(path);
    expect(result.degraded).toBe(false);
    expect(result.localFallbackOverride).toBe(true);
    expect(isLocalFallbackAuthorized(result)).toBe(true);
  });

  test("corrupt config honors and records explicit local fallback override", () => {
    const path = join(dir, "controller.toml");
    writeFileSync(path, "enabled = true\nport = oops\n");
    process.env.BUILD_REMOTE_LOCAL_FALLBACK = "1";
    const result: ConfigLoadResult = loadConfigResult(path);
    expect(result.degraded).toBe(true);
    expect(result.localFallbackOverride).toBe(true);
    expect(isLocalFallbackAuthorized(result)).toBe(true);
    expect(result.incident?.detail).toContain(
      "BUILD_REMOTE_LOCAL_FALLBACK=1 honored",
    );
  });
});
