import { describe, expect, test } from "bun:test";
import { buildAdapters, requireOffloadToken, resolveOffloadConnection } from "./index";
import { defaultConfig } from "../config";
import { CollectorFatalError } from "../errors";
import { mkdtempSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { RequestsStore } from "../requests/requests-store";

const TOKEN = "test-collector-token";

describe("requireOffloadToken", () => {
  test("returns trimmed non-empty token", () => {
    expect(requireOffloadToken(`  ${TOKEN}  `)).toBe(TOKEN);
  });

  test("empty token throws CollectorFatalError with code TOKEN_EMPTY", () => {
    expect(() => requireOffloadToken("")).toThrow(CollectorFatalError);
    try {
      requireOffloadToken("   ");
    } catch (err) {
      expect(err).toBeInstanceOf(CollectorFatalError);
      expect((err as CollectorFatalError).code).toBe("TOKEN_EMPTY");
    }
  });
});

describe("resolveOffloadConnection", () => {
  test("resolves defaults and passes through validated token", () => {
    const connection = resolveOffloadConnection(defaultConfig(), TOKEN);
    expect(connection).toEqual({
      controllerUrl: "http://127.0.0.1:8787",
      metricsUrl: "http://127.0.0.1:8787",
      token: TOKEN,
    });
  });

  test("empty token throws TOKEN_EMPTY before connection is returned", () => {
    expect(() => resolveOffloadConnection(defaultConfig(), "")).toThrow(CollectorFatalError);
  });
});

describe("buildAdapters offload token", () => {
  test("empty token throws TOKEN_EMPTY when offload is enabled", () => {
    expect(() => buildAdapters(defaultConfig(), "")).toThrow(CollectorFatalError);
    try {
      buildAdapters(defaultConfig(), "");
    } catch (err) {
      expect((err as CollectorFatalError).code).toBe("TOKEN_EMPTY");
    }
  });
});

describe("buildAdapters deploy status", () => {
  test("includes deploy status only when explicitly enabled", () => {
    expect(buildAdapters(defaultConfig(), TOKEN).some((adapter) => adapter.id === "deploy-status")).toBe(false);

    const config = defaultConfig();
    config.adapters["deploy-status"] = { enabled: true };
    expect(buildAdapters(config, TOKEN).some((adapter) => adapter.id === "deploy-status")).toBe(true);
  });
});

describe("buildAdapters github checks", () => {
  test("fails closed to disabled when repo or token config is absent", () => {
    const requests = new RequestsStore(join(mkdtempSync(join(tmpdir(), "overdeck-github-config-")), "requests.sqlite"));
    expect(buildAdapters(defaultConfig(), TOKEN, requests).some((adapter) => adapter.id === "github-checks")).toBe(false);
    const config = defaultConfig(); config.adapters["github-checks"] = { enabled: true, repo: "owner/overdeck" };
    expect(buildAdapters(config, TOKEN, requests).some((adapter) => adapter.id === "github-checks")).toBe(false); requests.close();
  });
  test("enables with a configured repo and non-empty token file", () => {
    const root = mkdtempSync(join(tmpdir(), "overdeck-github-config-")); const tokenPath = join(root, "token");
    writeFileSync(tokenPath, "github-token\n", { mode: 0o600 }); const requests = new RequestsStore(join(root, "requests.sqlite"));
    const config = defaultConfig(); config.adapters["github-checks"] = { enabled: true, repo: "owner/overdeck", tokenPath };
    expect(buildAdapters(config, TOKEN, requests).some((adapter) => adapter.id === "github-checks")).toBe(true); requests.close();
  });
});
