import { describe, it, expect, beforeEach } from 'vitest';
import { Repository } from '../../db/repository.js';
import { makeA2aUserBuilder, A2aAuthenticatedUser } from './user-builder.js';
import { UnauthenticatedUser } from '@a2a-js/sdk/server';

function fakeProvider(token: string, payload: any) {
  return { AccessToken: { async find(v: string) { return v === token ? payload : undefined; } } } as any;
}

function reqWith(auth?: string) {
  return { headers: auth ? { authorization: auth } : {} } as any;
}

const NOW_ISO = '2026-06-27T00:00:00Z';

describe('makeA2aUserBuilder', () => {
  let repo: Repository;

  beforeEach(() => {
    repo = new Repository(':memory:');
    // Seed active user u1 (mirrors token-auth.test.ts seeding)
    (repo as any).db.prepare(
      "INSERT INTO users (id, email, name, avatar_url, role, status, created_at, updated_at) " +
      "VALUES ('u1','u1@test','User One',NULL,'user','active','2026-01-01','2026-01-01')",
    ).run();
    repo.createA2aDelegation({
      id: 'd1', userId: 'u1', clientId: 'cli1', grantId: 'g1',
      grantedSpaceIds: ['s1'], grantedSkills: ['research'], audience: 'https://m/a2a',
      expiresAt: null, revokedAt: null,
    });
  });

  it('returns an authenticated User carrying the principal when Bearer token is valid', async () => {
    const provider = fakeProvider('tok', { accountId: 'u1', grantId: 'g1', scope: 'openid a2a.read' });
    const builder = makeA2aUserBuilder(provider, repo);
    const user = await builder(reqWith('Bearer tok'));

    expect(user.isAuthenticated).toBe(true);
    expect(user.userName).toBe('u1');
    expect(user).toBeInstanceOf(A2aAuthenticatedUser);
    expect((user as A2aAuthenticatedUser).a2aPrincipal.actingUserId).toBe('u1');
  });

  it('returns UnauthenticatedUser when no Bearer header is present', async () => {
    const provider = fakeProvider('tok', { accountId: 'u1', grantId: 'g1', scope: 'openid a2a.read' });
    const builder = makeA2aUserBuilder(provider, repo);
    const user = await builder(reqWith());

    expect(user.isAuthenticated).toBe(false);
    expect(user).toBeInstanceOf(UnauthenticatedUser);
  });

  it('returns UnauthenticatedUser when Bearer token is invalid', async () => {
    const provider = fakeProvider('tok', { accountId: 'u1', grantId: 'g1', scope: 'openid a2a.read' });
    const builder = makeA2aUserBuilder(provider, repo);
    const user = await builder(reqWith('Bearer WRONG'));

    expect(user.isAuthenticated).toBe(false);
    expect(user).toBeInstanceOf(UnauthenticatedUser);
  });

  it('returns UnauthenticatedUser when token scope lacks a2a.read', async () => {
    const provider = fakeProvider('tok', { accountId: 'u1', grantId: 'g1', scope: 'openid' });
    const builder = makeA2aUserBuilder(provider, repo);
    const user = await builder(reqWith('Bearer tok'));

    expect(user.isAuthenticated).toBe(false);
    expect(user).toBeInstanceOf(UnauthenticatedUser);
  });
});
