import { describe, expect, test } from "bun:test";

import type { ResolveContext } from "../../../../../src/server/checker/runner/types";
import type { ResolvedWsTarget } from "../../../../../src/server/checker/runner/ws/types";
import type { RawTargetConfig } from "../../../../../src/server/checker/types";

import { checkerRegistry } from "../../../../../src/server/checker/runner";

function asWs(resolved: ReturnType<ReturnType<typeof checkerRegistry.get>["resolve"]>): ResolvedWsTarget {
  return resolved as ResolvedWsTarget;
}

function makeRawTarget(overrides?: Partial<RawTargetConfig>): RawTargetConfig {
  return {
    id: "test-ws",
    type: "ws",
    ws: { url: "ws://example.com/ws" },
    ...overrides,
  };
}

function makeResolveContext(overrides?: Partial<ResolveContext>): ResolveContext {
  return {
    configDir: "/tmp",
    defaultIntervalMs: 30000,
    defaultTimeoutMs: 10000,
    ...overrides,
  };
}

describe("WsChecker resolve", () => {
  const checker = checkerRegistry.tryGet("ws")!;

  test("最简 target 填充默认值", () => {
    const resolved = asWs(checker.resolve(makeRawTarget(), makeResolveContext()));
    expect(resolved.type).toBe("ws");
    expect(resolved.ws.url).toBe("ws://example.com/ws");
    expect(resolved.ws.headers).toEqual({});
    expect(resolved.ws.ignoreSSL).toBe(false);
    expect(resolved.ws.maxMessageBytes).toBe(4096);
    expect(resolved.ws.receiveTimeout).toBe(5000);
    expect(resolved.ws.send).toBeUndefined();
    expect(resolved.ws.subprotocols).toEqual([]);
    expect(resolved.expect).toEqual({ connected: true });
    expect(resolved.group).toBe("default");
    expect(resolved.intervalMs).toBe(30000);
    expect(resolved.timeoutMs).toBe(10000);
  });

  test("完整配置正确 resolve", () => {
    const raw = makeRawTarget({
      expect: { connected: true, durationMs: { lte: 5000 } },
      ws: {
        headers: { Authorization: "Bearer token" },
        ignoreSSL: true,
        maxMessageBytes: "8KB",
        receiveTimeout: 3000,
        send: "ping",
        subprotocols: ["json"],
        url: "wss://api.example.com/ws",
      },
    });
    const resolved = asWs(checker.resolve(raw, makeResolveContext()));
    expect(resolved.ws.url).toBe("wss://api.example.com/ws");
    expect(resolved.ws.headers).toEqual({ Authorization: "Bearer token" });
    expect(resolved.ws.ignoreSSL).toBe(true);
    expect(resolved.ws.maxMessageBytes).toBe(8192);
    expect(resolved.ws.receiveTimeout).toBe(3000);
    expect(resolved.ws.send).toBe("ping");
    expect(resolved.ws.subprotocols).toEqual(["json"]);
    expect(resolved.expect?.connected).toBe(true);
  });

  test("expect 默认 connected=true", () => {
    const raw = makeRawTarget({ expect: { durationMs: { lte: 1000 } } });
    const resolved = asWs(checker.resolve(raw, makeResolveContext()));
    expect(resolved.expect?.connected).toBe(true);
  });

  test("expect.connected=false 保留", () => {
    const raw = makeRawTarget({ expect: { connected: false } });
    const resolved = asWs(checker.resolve(raw, makeResolveContext()));
    expect(resolved.expect?.connected).toBe(false);
  });

  test("serialize 返回正确格式", () => {
    const resolved = asWs(checker.resolve(makeRawTarget(), makeResolveContext()));
    const serialized = checker.serialize(resolved);
    expect(serialized.target).toBe("ws://example.com/ws");
    const config = JSON.parse(serialized.config) as Record<string, unknown>;
    expect(config["url"]).toBe("ws://example.com/ws");
    expect(config["ignoreSSL"]).toBe(false);
    expect(config["receiveTimeout"]).toBe(5000);
  });
});
