/**
 * wechatTokenManager.test.js
 * Unit tests for WeChat Access Token management.
 */

const { describe, it, before, after } = require('node:test');
const assert = require('node:assert/strict');

// Mock wx environment for WeChat mini game server
// The wechatTokenManager uses wx APIs on client, but on server it uses
// HTTPS requests to WeChat API. We test the server-side module.

const WechatTokenManager = require('../services/wechatTokenManager');

describe('WechatTokenManager', () => {
  let manager;

  before(() => {
    manager = new WechatTokenManager();
  });

  after(() => {
    // Clean up any timers
    if (manager._refreshTimer) {
      clearInterval(manager._refreshTimer);
    }
  });

  it('should initialize with no token', () => {
    assert.strictEqual(manager._accessToken, '');
    assert.strictEqual(manager._expiresAt, 0);
    assert.strictEqual(manager._isAvailable, false);
  });

  it('should report unavailable when no token is set', () => {
    const available = manager.isAvailable();
    assert.strictEqual(available, false);
  });

  it('should report available when valid token is set', () => {
    manager._accessToken = 'test_token_123';
    manager._expiresAt = Date.now() + 7000 * 1000; // 7000 seconds from now
    manager._isAvailable = true;
    assert.strictEqual(manager.isAvailable(), true);
  });

  it('should return token when available', () => {
    manager._accessToken = 'test_token_456';
    manager._expiresAt = Date.now() + 7000 * 1000;
    manager._isAvailable = true;
    const token = manager.getAccessToken();
    assert.strictEqual(token, 'test_token_456');
  });

  it('should return empty string when token is expired', () => {
    manager._accessToken = 'expired_token';
    manager._expiresAt = Date.now() - 1000; // expired
    manager._isAvailable = false;
    const token = manager.getAccessToken();
    assert.strictEqual(token, '');
  });

  it('should handle token refresh failure gracefully', async () => {
    // Create a manager with invalid appid/secret to test failure
    const failManager = new WechatTokenManager();
    failManager.appId = 'invalid_appid';
    failManager.appSecret = 'invalid_secret';
    // Override retry delays to speed up test
    failManager._isRefreshing = false;

    // The _refreshToken will attempt with retries, but should not throw.
    // Use a short timeout to avoid long waits.
    const result = await Promise.race([
      failManager._refreshToken(),
      new Promise((resolve) => setTimeout(() => resolve(false), 5000)),
    ]);

    assert.strictEqual(failManager.isAvailable(), false);
    // Clean up any pending timers
    failManager.destroy();
  });

  it('should not leak token in toString', () => {
    manager._accessToken = 'sensitive_token_xyz';
    const str = manager.toString();
    assert.strictEqual(str.includes('sensitive_token_xyz'), false);
  });
});
