import 'dart:io';

import 'package:backend/authenticator.dart';
import 'package:dart_frog/dart_frog.dart';

Authenticator? _authenticator;

Middleware authenticatorMiddlewareProvider() {
  return provider<Authenticator>((context) => _authenticator ??= Authenticator());
}

typedef Applies = Future<bool> Function(RequestContext context);

Future<bool> _defaultApplies(RequestContext context) async => true;

Middleware tokenAuthMiddleware({
  Applies applies = _defaultApplies,
}) {
  return (handler) => (context) async {
        if (!await applies(context)) {
          return handler(context);
        }
        final auth = context.read<Authenticator>();
        // use `auth.verifyToken(token)` to check the jwt that came in the request header bearer
        final authHeader = context.request.headers['authorization'] ?? context.request.headers['Authorization'];
        final auths = authHeader?.split(' ');
        if (authHeader == null || !authHeader.startsWith('Bearer ') || auths == null || auths.length != 2) {
          log.fine('Denied request - No Auth - ${context.request.method.value} ${context.request.uri.path}');
          return Response(statusCode: HttpStatus.unauthorized);
        }
        final token = auths.last;

        final (user, tokStatus) = await auth.verifyToken(token);

        if (user == null) {
          log.fine(
            'Denied request - Bad Auth:$tokStatus - ${context.request.method.value} ${context.request.uri.path}',
          );
          return Response(statusCode: HttpStatus.unauthorized);
        }

        return handler(
          context.provide(
            () => user,
          ),
        );
      };
}