/**
 * Tests for server/utils/tokenStore.js
 *
 * The token store persists Emby access tokens to disk (JSON file) so users
 * survive server restarts without re-logging in. Tests verify the store/get/
 * clear lifecycle, TTL expiry, and atomic write behaviour.
 *
 * Each test imports a FRESH module instance (vi.resetModules) so the
 * module-level singleton state (loaded from disk) doesn't bleed between tests.
 */

import { vi } from 'vitest';
import fs from 'fs';
import path from 'path';
import os from 'os';

// Each test gets its own isolated temp dir
let tmpDir;
let tokenStore;

async function freshStore(dir) {
  vi.resetModules();
  process.env.DATA_DIR = dir;
  const mod = await import('../../server/utils/tokenStore.js');
  return mod;
}

beforeEach(async () => {
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sofarr-ts-'));
  tokenStore = await freshStore(tmpDir);
});

afterEach(() => {
  fs.rmSync(tmpDir, { recursive: true, force: true });
});

describe('tokenStore', () => {
  it('stores and retrieves a token', () => {
    tokenStore.storeToken('user1', 'access-token-abc');
    const result = tokenStore.getToken('user1');
    expect(result).not.toBeNull();
    expect(result.accessToken).toBe('access-token-abc');
  });

  it('returns null for an unknown user', () => {
    expect(tokenStore.getToken('nobody')).toBeNull();
  });

  it('clears a stored token', () => {
    tokenStore.storeToken('user1', 'token-xyz');
    tokenStore.clearToken('user1');
    expect(tokenStore.getToken('user1')).toBeNull();
  });

  it('clearToken is a no-op for unknown user', () => {
    expect(() => tokenStore.clearToken('ghost')).not.toThrow();
  });

  it('overwrites existing token on re-store', () => {
    tokenStore.storeToken('user1', 'old-token');
    tokenStore.storeToken('user1', 'new-token');
    expect(tokenStore.getToken('user1').accessToken).toBe('new-token');
  });

  it('persists to disk (tokens.json exists after store)', () => {
    tokenStore.storeToken('u1', 'tok');
    const storePath = path.join(tmpDir, 'tokens.json');
    expect(fs.existsSync(storePath)).toBe(true);
    const data = JSON.parse(fs.readFileSync(storePath, 'utf8'));
    expect(data.u1.accessToken).toBe('tok');
  });

  it('expires tokens older than 31 days on read', () => {
    // Write an already-expired entry directly to disk
    const expired = Date.now() - (32 * 24 * 60 * 60 * 1000);
    const storePath = path.join(tmpDir, 'tokens.json');
    fs.writeFileSync(storePath, JSON.stringify({ u1: { accessToken: 'old', createdAt: expired } }));
    // Re-import to load from disk
    vi.resetModules();
    return import('../../server/utils/tokenStore.js').then(mod => {
      expect(mod.getToken('u1')).toBeNull();
    });
  });
});
