/**
 * Tests for token.ts module
 *
 * Tests cover:
 * - Token resolution from config
 * - Token resolution from environment variable
 * - Fallback behavior when token not found
 * - Account ID normalization
 */

import type { OpenClawConfig } from "openclaw/plugin-sdk";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveTwitchToken, type TwitchTokenSource } from "./token.js";

describe("token", () => {
  // Multi-account config for testing non-default accounts
  const mockMultiAccountConfig = {
    channels: {
      twitch: {
        accounts: {
          default: {
            username: "testbot",
            accessToken: "oauth:config-token",
          },
          other: {
            username: "otherbot",
            accessToken: "oauth:other-token",
          },
        },
      },
    },
  } as unknown as OpenClawConfig;

  // Simplified single-account config
  const mockSimplifiedConfig = {
    channels: {
      twitch: {
        username: "testbot",
        accessToken: "oauth:config-token",
      },
    },
  } as unknown as OpenClawConfig;

  beforeEach(() => {
    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.restoreAllMocks();
    delete process.env.OPENCLAW_TWITCH_ACCESS_TOKEN;
  });

  describe("resolveTwitchToken", () => {
    it("should resolve token from simplified config for default account", () => {
      const result = resolveTwitchToken(mockSimplifiedConfig, { accountId: "default" });

      expect(result.token).toBe("oauth:config-token");
      expect(result.source).toBe("config");
    });

    it("should resolve token from config for non-default account (multi-account)", () => {
      const result = resolveTwitchToken(mockMultiAccountConfig, { accountId: "other" });

      expect(result.token).toBe("oauth:other-token");
      expect(result.source).toBe("config");
    });

    it("should prioritize config token over env var (simplified config)", () => {
      process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";

      const result = resolveTwitchToken(mockSimplifiedConfig, { accountId: "default" });

      // Config token should be used even if env var exists
      expect(result.token).toBe("oauth:config-token");
      expect(result.source).toBe("config");
    });

    it("should use env var when config token is empty (simplified config)", () => {
      process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";

      const configWithEmptyToken = {
        channels: {
          twitch: {
            username: "testbot",
            accessToken: "",
          },
        },
      } as unknown as OpenClawConfig;

      const result = resolveTwitchToken(configWithEmptyToken, { accountId: "default" });

      expect(result.token).toBe("oauth:env-token");
      expect(result.source).toBe("env");
    });

    it("should return empty token when neither config nor env has token (simplified config)", () => {
      const configWithoutToken = {
        channels: {
          twitch: {
            username: "testbot",
            accessToken: "",
          },
        },
      } as unknown as OpenClawConfig;

      const result = resolveTwitchToken(configWithoutToken, { accountId: "default" });

      expect(result.token).toBe("");
      expect(result.source).toBe("none");
    });

    it("should not use env var for non-default accounts (multi-account)", () => {
      process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";

      const configWithoutToken = {
        channels: {
          twitch: {
            accounts: {
              secondary: {
                username: "secondary",
                accessToken: "",
              },
            },
          },
        },
      } as unknown as OpenClawConfig;

      const result = resolveTwitchToken(configWithoutToken, { accountId: "secondary" });

      // Non-default accounts shouldn't use env var
      expect(result.token).toBe("");
      expect(result.source).toBe("none");
    });

    it("should handle missing account gracefully", () => {
      const configWithoutAccount = {
        channels: {
          twitch: {
            accounts: {},
          },
        },
      } as unknown as OpenClawConfig;

      const result = resolveTwitchToken(configWithoutAccount, { accountId: "nonexistent" });

      expect(result.token).toBe("");
      expect(result.source).toBe("none");
    });

    it("should handle missing Twitch config section", () => {
      const configWithoutSection = {
        channels: {},
      } as unknown as OpenClawConfig;

      const result = resolveTwitchToken(configWithoutSection, { accountId: "default" });

      expect(result.token).toBe("");
      expect(result.source).toBe("none");
    });
  });

  describe("TwitchTokenSource type", () => {
    it("should have correct values", () => {
      const sources: TwitchTokenSource[] = ["env", "config", "none"];

      expect(sources).toContain("env");
      expect(sources).toContain("config");
      expect(sources).toContain("none");
    });
  });
});
