using CMSMicroservice.Application.Common.FileManager;
using Google.Protobuf;
using Google.Protobuf.Reflection;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.Extensions.Logging;
using System.Collections;
using System.Collections.Generic;

namespace CMSMicroservice.WebApi.Interceptors;

/// <summary>
/// gRPC Interceptor — بعد از اجرای هر سرویس، فیلدهای تصویری response را
/// از مسیر نسبی دیسک به base64 data-URI تبدیل می‌کند
/// </summary>
public class ImagePathResolverInterceptor : Interceptor
{
    private readonly IFileManager _fileManager;
    private readonly ILogger<ImagePathResolverInterceptor> _logger;

    // نام فیلدهایی که مسیر تصویر هستند
    private static readonly HashSet<string> ImageFieldNames = new(StringComparer.OrdinalIgnoreCase)
    {
        "image_path",
        "thumbnail_path",
        "image_thumbnail_path",
        "featured_image_path",
        "featured_image_thumbnail_path",
        "hero_image_path",
        "product_thumbnail_path",
        "avatar_path",
        "avatar_url",
        "avatar"
    };

    public ImagePathResolverInterceptor(IFileManager fileManager, ILogger<ImagePathResolverInterceptor> logger)
    {
        _fileManager = fileManager;
        _logger = logger;
    }

    // ── Unary call (اکثر gRPC‌ها) ──
    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        var response = await continuation(request, context);

        if (response is IMessage message)
        {
            ResolveImagePaths(message);
        }

        return response;
    }

    // ── Server streaming ──
    public override async Task ServerStreamingServerHandler<TRequest, TResponse>(
        TRequest request,
        IServerStreamWriter<TResponse> responseStream,
        ServerCallContext context,
        ServerStreamingServerMethod<TRequest, TResponse> continuation)
    {
        var wrappedStream = new ImageResolvingStreamWriter<TResponse>(responseStream, this);
        await continuation(request, wrappedStream, context);
    }

    /// <summary>
    /// بازگشتی: تمام فیلدهای string با نام تصویری را resolve می‌کند
    /// شامل فیلدهای تکراری (repeated) و زیر-پیام‌ها (sub-messages)
    /// </summary>
    internal void ResolveImagePaths(IMessage message)
    {
        var descriptor = message.Descriptor;

        foreach (var field in descriptor.Fields.InFieldNumberOrder())
        {
            try
            {
                if (field.FieldType == FieldType.String && ImageFieldNames.Contains(field.Name))
                {
                    // فیلد string ساده
                    var accessor = field.Accessor;
                    var value = accessor.GetValue(message) as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        var resolved = _fileManager.ResolveImageUrl(value);
                        accessor.SetValue(message, resolved);
                    }
                }
                else if (field.FieldType == FieldType.Message)
                {
                    if (field.IsRepeated)
                    {
                        // repeated sub-message
                        var list = field.Accessor.GetValue(message) as System.Collections.IList;
                        if (list != null)
                        {
                            foreach (var item in list)
                            {
                                if (item is IMessage subMsg)
                                    ResolveImagePaths(subMsg);
                            }
                        }
                    }
                    else
                    {
                        // فیلد oneof یا فیلد optional message
                        var subMessage = field.Accessor.GetValue(message) as IMessage;
                        if (subMessage != null)
                        {
                            // Google.Protobuf.WellKnownTypes.StringValue wrapper
                            if (subMessage is Google.Protobuf.WellKnownTypes.StringValue sv
                                && ImageFieldNames.Contains(field.Name))
                            {
                                if (!string.IsNullOrEmpty(sv.Value))
                                {
                                    sv.Value = _fileManager.ResolveImageUrl(sv.Value);
                                }
                            }
                            else
                            {
                                ResolveImagePaths(subMessage);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Error resolving image path for field {Field}", field.Name);
            }
        }
    }

    /// <summary>
    /// Wrapper برای Server Streaming — هر پیام قبل از ارسال resolve می‌شود
    /// </summary>
    private class ImageResolvingStreamWriter<T> : IServerStreamWriter<T> where T : class
    {
        private readonly IServerStreamWriter<T> _inner;
        private readonly ImagePathResolverInterceptor _interceptor;

        public ImageResolvingStreamWriter(IServerStreamWriter<T> inner, ImagePathResolverInterceptor interceptor)
        {
            _inner = inner;
            _interceptor = interceptor;
        }

        public WriteOptions? WriteOptions
        {
            get => _inner.WriteOptions;
            set => _inner.WriteOptions = value;
        }

        public Task WriteAsync(T message)
        {
            if (message is IMessage msg)
                _interceptor.ResolveImagePaths(msg);
            return _inner.WriteAsync(message);
        }
    }
}
