using System.Text.Json;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Models.Auth;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// 微信发货重试后台服务
/// 定期检查 Redis 中失败的发货订单并重试
/// </summary>
public class ShippingRetryBackgroundService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly IRedisService _redisService;
    private readonly ILogger<ShippingRetryBackgroundService> _logger;

    private const int MaxRetryCount = 10;           // 最大重试次数
    private const int RetryIntervalSeconds = 30;    // 重试间隔（秒）
    private const int CheckIntervalSeconds = 30;    // 检查间隔（秒）
    private const string RetryKeyPattern = "post_order:*";

    public ShippingRetryBackgroundService(
        IServiceScopeFactory scopeFactory,
        IRedisService redisService,
        ILogger<ShippingRetryBackgroundService> logger)
    {
        _scopeFactory = scopeFactory;
        _redisService = redisService;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("发货重试后台服务已启动");

        // 启动时等待一小段时间，让其他服务初始化完成
        await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await ProcessFailedShippingOrdersAsync(stoppingToken);
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理发货重试时发生异常");
            }

            try
            {
                await Task.Delay(TimeSpan.FromSeconds(CheckIntervalSeconds), stoppingToken);
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
        }

        _logger.LogInformation("发货重试后台服务已停止");
    }

    private async Task ProcessFailedShippingOrdersAsync(CancellationToken stoppingToken)
    {
        // 获取所有发货失败的订单键
        var failedOrderKeys = await _redisService.GetKeysAsync(RetryKeyPattern);

        if (failedOrderKeys == null || !failedOrderKeys.Any())
        {
            return;
        }

        var keysList = failedOrderKeys.ToList();
        _logger.LogInformation("发现 {Count} 个待重试的发货订单", keysList.Count);

        var nowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

        foreach (var key in keysList)
        {
            if (stoppingToken.IsCancellationRequested)
                break;

            try
            {
                await ProcessSingleOrderAsync(key, nowTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理发货重试订单失败: Key={Key}", key);
            }
        }
    }


    private async Task ProcessSingleOrderAsync(string key, long nowTime)
    {
        // 获取订单数据
        var orderDataJson = await _redisService.GetStringAsync(key);
        if (string.IsNullOrEmpty(orderDataJson))
        {
            return;
        }

        ShippingRetryData? orderData;
        try
        {
            orderData = JsonSerializer.Deserialize<ShippingRetryData>(orderDataJson);
        }
        catch
        {
            // 数据格式错误，删除此键
            await _redisService.DeleteAsync(key);
            return;
        }

        if (orderData == null)
        {
            await _redisService.DeleteAsync(key);
            return;
        }

        // 检查重试次数
        if (orderData.retry_count >= MaxRetryCount)
        {
            _logger.LogWarning("订单 {OrderNo} 超过最大重试次数({MaxRetry})，已移除",
                orderData.order_num, MaxRetryCount);
            await _redisService.DeleteAsync(key);
            return;
        }

        // 检查是否达到重试间隔
        if ((nowTime - orderData.last_retry_time) < RetryIntervalSeconds)
        {
            return;
        }

        // 尝试重新发货 - 使用新的 scope 来解析 IWechatService
        _logger.LogInformation("开始重试发货: OrderNo={OrderNo}, RetryCount={RetryCount}",
            orderData.order_num, orderData.retry_count + 1);

        using var scope = _scopeFactory.CreateScope();
        var wechatService = scope.ServiceProvider.GetRequiredService<IWechatService>();

        var request = new WechatShippingRequest
        {
            OpenId = orderData.openid,
            OrderNo = orderData.order_num
        };

        var result = await wechatService.UploadShippingInfoAsync(request);

        if (result.Success)
        {
            // 发货成功，删除 Redis 记录
            await _redisService.DeleteAsync(key);
            _logger.LogInformation("订单 {OrderNo} 重试发货成功，已从重试队列移除", orderData.order_num);
        }
        else
        {
            // 发货失败，更新重试信息
            orderData.retry_count += 1;
            orderData.last_retry_time = nowTime;
            orderData.error_code = result.ErrorCode;
            orderData.error_msg = result.ErrorMessage ?? "unknown";

            var updatedJson = JsonSerializer.Serialize(orderData);
            await _redisService.SetStringAsync(key, updatedJson, TimeSpan.FromDays(3));

            _logger.LogWarning("订单 {OrderNo} 第 {RetryCount} 次重试发货失败: {ErrorMsg}",
                orderData.order_num, orderData.retry_count, result.ErrorMessage);
        }
    }
}

/// <summary>
/// 发货重试数据结构（与 Redis 存储格式一致）
/// </summary>
internal class ShippingRetryData
{
    public string openid { get; set; } = string.Empty;
    public string order_num { get; set; } = string.Empty;
    public int error_code { get; set; }
    public string error_msg { get; set; } = string.Empty;
    public int retry_count { get; set; }
    public long last_retry_time { get; set; }
    public long create_time { get; set; }
}
