using System;
using Grpc.Core;
using Grpc.Core.Interceptors;

namespace Auth {
    /// <summary>
    /// gRPC interceptor that attaches JWT Bearer token to requests.
    /// Reads token from TokenStorage on each request.
    /// </summary>
    public class JwtAuthInterceptor : Interceptor {
        private const string HeaderName = "Authorization";

        private string GetBearerHeader() {
            var token = TokenStorage.AccessToken;
            return string.IsNullOrEmpty(token) ? null : $"Bearer {token}";
        }

        public override TResponse BlockingUnaryCall<TRequest, TResponse>(
                TRequest request,
                ClientInterceptorContext<TRequest, TResponse> context,
                BlockingUnaryCallContinuation<TRequest, TResponse> continuation) {
            return continuation(request, ContextWithHeaders(context));
        }

        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
                TRequest request,
                ClientInterceptorContext<TRequest, TResponse> context,
                AsyncUnaryCallContinuation<TRequest, TResponse> continuation) {
            return continuation(request, ContextWithHeaders(context));
        }

        public override AsyncServerStreamingCall<TResponse>
        AsyncServerStreamingCall<TRequest, TResponse>(
                TRequest request,
                ClientInterceptorContext<TRequest, TResponse> context,
                AsyncServerStreamingCallContinuation<TRequest, TResponse> continuation) {
            return continuation(request, ContextWithHeaders(context));
        }

        public override AsyncClientStreamingCall<TRequest, TResponse>
        AsyncClientStreamingCall<TRequest, TResponse>(
                ClientInterceptorContext<TRequest, TResponse> context,
                AsyncClientStreamingCallContinuation<TRequest, TResponse> continuation) {
            return continuation(ContextWithHeaders(context));
        }

        public override AsyncDuplexStreamingCall<TRequest, TResponse>
        AsyncDuplexStreamingCall<TRequest, TResponse>(
                ClientInterceptorContext<TRequest, TResponse> context,
                AsyncDuplexStreamingCallContinuation<TRequest, TResponse> continuation) {
            return continuation(ContextWithHeaders(context));
        }

        private ClientInterceptorContext<TRequest, TResponse>
        ContextWithHeaders<TRequest, TResponse>(
                ClientInterceptorContext<TRequest, TResponse> original)
                where TRequest : class
                where TResponse : class {
            var bearerHeader = GetBearerHeader();
            if (string.IsNullOrEmpty(bearerHeader)) {
                // No token available - return original context
                // Auth service endpoints don't require token
                return original;
            }

            var headers = new Metadata();
            headers.Add(HeaderName, bearerHeader);

            return new ClientInterceptorContext<TRequest, TResponse>(
                    original.Method,
                    original.Host,
                    original.Options.WithHeaders(headers));
        }
    }
}
