import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { linePlugin } from "./channel.js";
import { setLineRuntime } from "./runtime.js";

const DEFAULT_ACCOUNT_ID = "default";

type LineRuntimeMocks = {
  writeConfigFile: ReturnType<typeof vi.fn>;
  resolveLineAccount: ReturnType<typeof vi.fn>;
};

function createRuntime(): { runtime: PluginRuntime; mocks: LineRuntimeMocks } {
  const writeConfigFile = vi.fn(async () => {});
  const resolveLineAccount = vi.fn(
    ({ cfg, accountId }: { cfg: OpenClawConfig; accountId?: string }) => {
      const lineConfig = (cfg.channels?.line ?? {}) as {
        tokenFile?: string;
        secretFile?: string;
        channelAccessToken?: string;
        channelSecret?: string;
        accounts?: Record<string, Record<string, unknown>>;
      };
      const entry =
        accountId && accountId !== DEFAULT_ACCOUNT_ID
          ? (lineConfig.accounts?.[accountId] ?? {})
          : lineConfig;
      const hasToken =
        // oxlint-disable-next-line typescript/no-explicit-any
        Boolean((entry as any).channelAccessToken) || Boolean((entry as any).tokenFile);
      // oxlint-disable-next-line typescript/no-explicit-any
      const hasSecret = Boolean((entry as any).channelSecret) || Boolean((entry as any).secretFile);
      return { tokenSource: hasToken && hasSecret ? "config" : "none" };
    },
  );

  const runtime = {
    config: { writeConfigFile },
    channel: { line: { resolveLineAccount } },
  } as unknown as PluginRuntime;

  return { runtime, mocks: { writeConfigFile, resolveLineAccount } };
}

describe("linePlugin gateway.logoutAccount", () => {
  beforeEach(() => {
    setLineRuntime(createRuntime().runtime);
  });

  it("clears tokenFile/secretFile on default account logout", async () => {
    const { runtime, mocks } = createRuntime();
    setLineRuntime(runtime);

    const cfg: OpenClawConfig = {
      channels: {
        line: {
          tokenFile: "/tmp/token",
          secretFile: "/tmp/secret",
        },
      },
    };

    const result = await linePlugin.gateway.logoutAccount({
      accountId: DEFAULT_ACCOUNT_ID,
      cfg,
    });

    expect(result.cleared).toBe(true);
    expect(result.loggedOut).toBe(true);
    expect(mocks.writeConfigFile).toHaveBeenCalledWith({});
  });

  it("clears tokenFile/secretFile on account logout", async () => {
    const { runtime, mocks } = createRuntime();
    setLineRuntime(runtime);

    const cfg: OpenClawConfig = {
      channels: {
        line: {
          accounts: {
            primary: {
              tokenFile: "/tmp/token",
              secretFile: "/tmp/secret",
            },
          },
        },
      },
    };

    const result = await linePlugin.gateway.logoutAccount({
      accountId: "primary",
      cfg,
    });

    expect(result.cleared).toBe(true);
    expect(result.loggedOut).toBe(true);
    expect(mocks.writeConfigFile).toHaveBeenCalledWith({});
  });
});
