import 'dart:developer';

import 'package:grpc/grpc.dart';

class AuthInterceptor extends ClientInterceptor {
  final String Function() getAccessToken;
  final String Function() getRefreshToken;

  AuthInterceptor({
    required this.getAccessToken,
    required this.getRefreshToken,
  });

  bool _isPublicEndpoint(String path) {
    return path.contains('/Public');
  }

  bool _isRefreshEndpoint(String path) {
    return path.contains('/RefreshToken');
  }

  Map<String, String> _buildMetadata(String path) {
    final metadata = <String, String>{};

    // Public endpoints → no token
    if (_isPublicEndpoint(path)) {
      log("Public endpoint, no tokens needed");
      return metadata;
    }

    String? token;

    // Refresh endpoint → use refresh token
    if (_isRefreshEndpoint(path)) {
      log("Adding a refresh token to the metadata");
      token = getRefreshToken();
    } else {
      log("Adding an acces token to the metadata");
      token = getAccessToken();
    }

    if (token.isNotEmpty) {
      metadata['authorization'] = 'Bearer $token';
    }
    return metadata;
  }

  @override
  ResponseStream<R> interceptStreaming<Q, R>(
    ClientMethod<Q, R> method,
    Stream<Q> requests,
    CallOptions options,
    ClientStreamingInvoker<Q, R> invoker,
  ) {
    // TODO: implement interceptStreaming
    throw UnimplementedError();
  }

  @override
  ResponseFuture<R> interceptUnary<Q, R>(
    ClientMethod<Q, R> method,
    Q request,
    CallOptions options,
    ClientUnaryInvoker<Q, R> invoker,
  ) {
    final modifiedOptions = options.mergedWith(
      CallOptions(metadata: _buildMetadata(method.path)),
    );
    return super.interceptUnary(method, request, modifiedOptions, invoker);
  }
}
