import 'package:gametime_server/api/auth_api.dart';
import 'package:gametime_server/application/application.dart';
import 'package:gametime_server/domain/domain.dart';
import 'package:shelf/shelf.dart';
import 'package:test/test.dart';

void main() {
  test('authentication middleware injects the authenticated request', () async {
    final user = UserAccount(
      id: 'user-1',
      email: 'user@example.com',
      passwordHash: 'hash',
      createdAt: DateTime.utc(2026, 7, 19, 12),
      updatedAt: DateTime.utc(2026, 7, 19, 12),
    );
    final session = AuthSession(
      id: 'session-1',
      userId: user.id,
      tokenHash: 'token-hash',
      issuedAt: DateTime.utc(2026, 7, 19, 12),
      expiresAt: DateTime.utc(2026, 7, 20, 12),
    );
    final tokens = <String>[];
    final handler =
        authenticationMiddleware(({required token}) async {
          tokens.add(token);
          return AuthenticatedRequest(user: user, session: session);
        })((request) {
          final authenticated = authenticatedRequestFrom(request);
          return Response.ok(authenticated?.user.id ?? 'missing');
        });

    final response = await handler(
      Request(
        'GET',
        Uri.parse('http://localhost/protected'),
        headers: {'authorization': 'Bearer clear-token'},
      ),
    );

    expect(response.statusCode, 200);
    expect(await response.readAsString(), 'user-1');
    expect(tokens, ['clear-token']);
  });

  test(
    'authentication middleware rejects missing or invalid bearer tokens',
    () async {
      final handler = authenticationMiddleware(({required token}) async {
        throw const UnauthorizedException();
      })((request) => Response.ok('secret'));

      final missing = await handler(
        Request('GET', Uri.parse('http://localhost/protected')),
      );
      final invalid = await handler(
        Request(
          'GET',
          Uri.parse('http://localhost/protected'),
          headers: {'authorization': 'Bearer invalid-token'},
        ),
      );

      expect(missing.statusCode, 401);
      expect(invalid.statusCode, 401);
    },
  );
}
