using CMSMicroservice.Application.ClubFeatureCQ.Queries.GetUserClubFeatures;
using CMSMicroservice.Application.Common.Authorization;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Common;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Protobuf.Protos.Configuration;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace CMSMicroservice.WebApi.Services;

/// <summary>
/// سرویس تنظیمات سیستم — مقادیر پکیجی از Package entity خوانده می‌شوند
/// </summary>
public class ConfigurationService : ConfigurationContract.ConfigurationContractBase
{
    private readonly ILogger<ConfigurationService> _logger;
    private readonly ICurrentUserService _currentUserService;
    private readonly IMediator _mediator;
    private readonly IApplicationDbContext _context;

    public ConfigurationService(
        ILogger<ConfigurationService> logger,
        ICurrentUserService currentUserService,
        IMediator mediator,
        IApplicationDbContext context)
    {
        _logger = logger;
        _currentUserService = currentUserService;
        _mediator = mediator;
        _context = context;
    }

    /// <summary>
    /// دریافت تنظیمات با کلید خاص
    /// </summary>
    public override async Task<GetConfigurationByKeyResponse> GetConfigurationByKey(GetConfigurationByKeyRequest request, ServerCallContext context)
    {
        var response = new GetConfigurationByKeyResponse
        {
            Key = request.Key,
            Scope = request.Scope,
            IsActive = true,
            Created = Timestamp.FromDateTime(DateTime.UtcNow),
            LastModified = Timestamp.FromDateTime(DateTime.UtcNow)
        };

        // برای کلیدهای پکیجی، از دیتابیس می‌خوانیم
        var package = await GetBasePackageAsync(context.CancellationToken);
        response.Value = GetConfigurationValue(request.Key, package);
        response.Description = GetConfigurationDescription(request.Key);

        _logger.LogDebug("Configuration requested: Key={Key}, Value={Value}", request.Key, response.Value);

        return response;
    }

    /// <summary>
    /// دریافت تنظیمات باشگاه مشتریان
    /// </summary>
    public override async Task<GetClubConfigurationResponse> GetClubConfiguration(Empty request, ServerCallContext context)
    {
        var package = await GetBasePackageAsync(context.CancellationToken);

        var response = new GetClubConfigurationResponse
        {
            ActivationFee = package.ActivationFee,
            MembershipGiftValue = package.ActivationFee
        };

        _logger.LogDebug("Club configuration requested: ActivationFee={ActivationFee}, GiftValue={GiftValue}", 
            response.ActivationFee, response.MembershipGiftValue);

        return response;
    }

    /// <summary>
    /// دریافت ویژگی‌های باشگاه مشتریان برای کاربر جاری
    /// </summary>
    public override async Task<GetClubFeaturesResponse> GetClubFeatures(Empty request, ServerCallContext context)
    {
        // دریافت UserId از JWT
        if (!long.TryParse(_currentUserService.UserId, out var userId) || userId <= 0)
        {
            _logger.LogWarning("GetClubFeatures called without valid user authentication");
            return new GetClubFeaturesResponse(); // لیست خالی برای کاربران غیر احراز هویت شده
        }

        // فراخوانی GetUserClubFeatures از طریق MediatR (CQRS داخلی)
        var query = new GetUserClubFeaturesQuery { UserId = userId };
        var userFeatures = await _mediator.Send(query, context.CancellationToken);

        // تبدیل به فرمت GetClubFeaturesResponse
        var response = new GetClubFeaturesResponse();
        foreach (var feature in userFeatures)
        {
            response.Features.Add(new ClubFeatureModel
            {
                Id = feature.ClubFeatureId,
                Title = feature.FeatureTitle ?? string.Empty,
                Description = feature.FeatureDescription ?? string.Empty,
                IsEnabled = feature.IsActive,
                DisplayOrder = feature.SortOrder,
                GrantedAt = Timestamp.FromDateTime(DateTime.SpecifyKind(feature.GrantedAt, DateTimeKind.Utc)),
                CreatedAt = Timestamp.FromDateTime(DateTime.SpecifyKind(feature.CreatedAt, DateTimeKind.Utc)),
                Notes = feature.Notes ?? string.Empty
            });
        }

        _logger.LogDebug("Club features requested for user {UserId}: {Count} features returned", userId, response.Features.Count);

        return response;
    }

    /// <summary>
    /// دریافت تمام تنظیمات
    /// </summary>
    [RequiresPermission(PermissionNames.SettingsView)]
    public override async Task<GetAllConfigurationsResponse> GetAllConfigurations(GetAllConfigurationsRequest request, ServerCallContext context)
    {
        var package = await GetBasePackageAsync(context.CancellationToken);
        var response = new GetAllConfigurationsResponse();

        // Club Settings (از Package)
        response.Models.Add(CreateConfigModel("Club.ActivationFee", package.ActivationFee.ToString(), "هزینه فعال‌سازی عضویت باشگاه", 2));
        response.Models.Add(CreateConfigModel("Club.MembershipGiftValue", package.ActivationFee.ToString(), "مبلغ هدیه حق عضویت باشگاه", 2));

        // Commission Settings (سقف‌ها از Package)
        response.Models.Add(CreateConfigModel("Commission.MinWithdrawalAmount", SystemConstants.CommissionMinWithdrawalAmount.ToString(), "حداقل مبلغ برداشت", 3));
        response.Models.Add(CreateConfigModel("Commission.MaxWeeklyBalancesPerLeg", package.MaxBalancesPerLeg.ToString(), "سقف تعادل هفتگی برای هر دست", 3));
        response.Models.Add(CreateConfigModel("Commission.MaxNetworkLevel", package.MaxNetworkLevel.ToString(), "حداکثر عمق شبکه برای محاسبه کمیسیون", 3));
        response.Models.Add(CreateConfigModel("Commission.CashWithdrawalEnabled", SystemConstants.CommissionCashWithdrawalEnabled.ToString(), "امکان برداشت نقدی", 3));
        response.Models.Add(CreateConfigModel("Commission.CalculationStrategy", SystemConstants.CommissionCalculationStrategy, "روش محاسبه کمیسیون", 3));

        // Network Settings
        response.Models.Add(CreateConfigModel("Network.AllowOrphanNodes", SystemConstants.NetworkAllowOrphanNodes.ToString(), "اجازه حذف والدین با فرزند", 1));
        response.Models.Add(CreateConfigModel("Network.MaxChildrenPerLeg", SystemConstants.NetworkMaxChildrenPerLeg.ToString(), "حداکثر تعداد فرزند مستقیم در هر پا", 1));

        // Package Settings (از Package)
        response.Models.Add(CreateConfigModel("Package.BasePackageAmount", package.Price.ToString(), "مبلغ پکیج پایه", 0));
        response.Models.Add(CreateConfigModel("Package.DayaLoanAmount", package.Price.ToString(), "مبلغ وام دایا", 0));

        // Magic Wallet Settings (از Package)
        response.Models.Add(CreateConfigModel("MagicWallet.Multiplier", package.MagicWalletMultiplier.ToString(), "ضریب شارژ کیف‌پول جادویی", 0));
        response.Models.Add(CreateConfigModel("MagicWallet.MaxDeposit", package.MagicWalletMaxDeposit.ToString(), "سقف واریز هر دور جادویی", 0));
        response.Models.Add(CreateConfigModel("MagicWallet.MaxCredit", package.MagicWalletMaxCredit.ToString(), "سقف اعتبار هر دور جادویی", 0));

        // System Settings
        response.Models.Add(CreateConfigModel("System.MaintenanceMode", SystemConstants.SystemMaintenanceMode.ToString(), "حالت تعمیر و نگهداری", 0));
        response.Models.Add(CreateConfigModel("System.EnableAuditLog", SystemConstants.SystemEnableAuditLog.ToString(), "فعال‌سازی لاگ تغییرات", 0));

        // Shop Settings
        response.Models.Add(CreateConfigModel("Shop.VAT", SystemConstants.ShopVAT.ToString(), "مالیات بر ارزش افزوده", 0));

        return response;
    }

    /// <summary>
    /// سایر عملیات‌ها که فعلاً پیاده‌سازی نشده‌اند (چون از constant استفاده می‌کنیم)
    /// </summary>
    [RequiresPermission(PermissionNames.SettingsManageConfiguration)]
    public override Task<Empty> CreateOrUpdateConfiguration(CreateOrUpdateConfigurationRequest request, ServerCallContext context)
    {
        _logger.LogWarning("CreateOrUpdateConfiguration called but SystemConstants are read-only. Key: {Key}", request.Key);
        throw new RpcException(new Status(StatusCode.FailedPrecondition, "تنظیمات سیستم فقط خواندنی هستند. تغییر از طریق کد انجام می‌شود"));
    }

    #region [ARCHIVED] DeactivateConfiguration & GetConfigurationHistory — SystemConstants ثابت هستند، این RPCها بی‌معنی
    [RequiresPermission(PermissionNames.SettingsManageConfiguration)]
    [Obsolete("ARCHIVED: SystemConstants are read-only — deactivation is meaningless")]
    public override Task<Empty> DeactivateConfiguration(DeactivateConfigurationRequest request, ServerCallContext context)
    {
        _logger.LogWarning("[ARCHIVED] DeactivateConfiguration called but SystemConstants are read-only. Key: {Key}", request.Key);
        throw new RpcException(new Status(StatusCode.FailedPrecondition, "تنظیمات سیستم فقط خواندنی هستند. غیرفعال‌سازی از طریق کد انجام می‌شود"));
    }

    [Obsolete("ARCHIVED: SystemConstants have no history — always returns empty")]
    public override Task<GetConfigurationHistoryResponse> GetConfigurationHistory(GetConfigurationHistoryRequest request, ServerCallContext context)
    {
        // [ARCHIVED] چون constant هستند، تاریخچه‌ای وجود نداره
        return Task.FromResult(new GetConfigurationHistoryResponse());
    }
    #endregion

    #region Private Helpers

    private static string GetConfigurationValue(string key, Package? package)
    {
        return key switch
        {
            "Club.ActivationFee" => (package?.ActivationFee ?? 0).ToString(),
            "Club.MembershipGiftValue" => (package?.ActivationFee ?? 0).ToString(),
            "Commission.MinWithdrawalAmount" => SystemConstants.CommissionMinWithdrawalAmount.ToString(),
            "Commission.MaxWeeklyBalancesPerLeg" => (package?.MaxBalancesPerLeg ?? 0).ToString(),
            "Commission.MaxNetworkLevel" => (package?.MaxNetworkLevel ?? 0).ToString(),
            "Commission.CashWithdrawalEnabled" => SystemConstants.CommissionCashWithdrawalEnabled.ToString(),
            "Commission.CalculationStrategy" => SystemConstants.CommissionCalculationStrategy,
            "Network.AllowOrphanNodes" => SystemConstants.NetworkAllowOrphanNodes.ToString(),
            "Network.MaxChildrenPerLeg" => SystemConstants.NetworkMaxChildrenPerLeg.ToString(),
            "Package.BasePackageAmount" => (package?.Price ?? 0).ToString(),
            "Package.DayaLoanAmount" => (package?.Price ?? 0).ToString(),
            "MagicWallet.Multiplier" => (package?.MagicWalletMultiplier ?? 0).ToString(),
            "MagicWallet.MaxDeposit" => (package?.MagicWalletMaxDeposit ?? 0).ToString(),
            "MagicWallet.MaxCredit" => (package?.MagicWalletMaxCredit ?? 0).ToString(),
            "System.MaintenanceMode" => SystemConstants.SystemMaintenanceMode.ToString(),
            "System.EnableAuditLog" => SystemConstants.SystemEnableAuditLog.ToString(),
            "Shop.VAT" => SystemConstants.ShopVAT.ToString(),
            _ => string.Empty
        };
    }

    private async Task<Package> GetBasePackageAsync(CancellationToken cancellationToken)
    {
        return await _context.Packages
            .FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
            ?? throw new RpcException(new Status(StatusCode.Internal, "پکیج پایه یافت نشد"));
    }

    private static string GetConfigurationDescription(string key)
    {
        return key switch
        {
            "Club.ActivationFee" => "هزینه فعال‌سازی عضویت باشگاه (تومان)",
            "Club.MembershipGiftValue" => "مبلغ هدیه حق عضویت باشگاه (تومان)",
            "Commission.MinWithdrawalAmount" => "حداقل مبلغ برداشت (تومان)",
            "Commission.MaxWeeklyBalancesPerLeg" => "سقف تعادل هفتگی برای هر دست",
            "Commission.MaxNetworkLevel" => "حداکثر عمق شبکه برای محاسبه کمیسیون",
            "Commission.CashWithdrawalEnabled" => "امکان برداشت نقدی",
            "Commission.CalculationStrategy" => "روش محاسبه کمیسیون",
            "Network.AllowOrphanNodes" => "اجازه حذف والدین با فرزند",
            "Network.MaxChildrenPerLeg" => "حداکثر تعداد فرزند مستقیم در هر پا",
            "Package.BasePackageAmount" => "مبلغ پکیج پایه (تومان)",
            "Package.DayaLoanAmount" => "مبلغ وام دایا (تومان)",
            "MagicWallet.Multiplier" => "ضریب شارژ کیف‌پول جادویی",
            "MagicWallet.MaxDeposit" => "سقف واریز هر دور جادویی (تومان)",
            "MagicWallet.MaxCredit" => "سقف اعتبار هر دور جادویی (تومان)",
            "System.MaintenanceMode" => "حالت تعمیر و نگهداری سیستم",
            "System.EnableAuditLog" => "فعال‌سازی لاگ تغییرات",
            "Shop.VAT" => "مالیات بر ارزش افزوده",
            _ => string.Empty
        };
    }

    private static ConfigurationModel CreateConfigModel(string key, string value, string description, int scope)
    {
        return new ConfigurationModel
        {
            Id = key.GetHashCode(),
            Key = key,
            Value = value,
            Description = description,
            Scope = scope,
            IsActive = true,
            Created = Timestamp.FromDateTime(DateTime.UtcNow)
        };
    }

    #endregion
}
