using TakeoutSaaS.Application.App.Personal.Dto;

namespace TakeoutSaaS.Application.App.Personal.Services;

/// <summary>
/// 个人中心模块状态构建服务。
/// </summary>
public sealed class PersonalModuleStatusService
{
    /// <summary>
    /// 构建成功状态。
    /// </summary>
    /// <param name="module">模块名称。</param>
    /// <param name="traceId">追踪标识。</param>
    /// <returns>模块状态 DTO。</returns>
    public PersonalModuleStatusDto BuildOk(string module, string? traceId = null)
    {
        // 1. 生成成功状态
        return new PersonalModuleStatusDto
        {
            Module = module,
            Status = "ok",
            TraceId = traceId
        };
    }

    /// <summary>
    /// 构建失败或降级状态。
    /// </summary>
    /// <param name="module">模块名称。</param>
    /// <param name="status">状态值：degraded/failed/timeout/skipped。</param>
    /// <param name="errorCode">错误码。</param>
    /// <param name="errorMessage">错误说明。</param>
    /// <param name="traceId">追踪标识。</param>
    /// <returns>模块状态 DTO。</returns>
    public PersonalModuleStatusDto BuildIssue(
        string module,
        string status,
        string? errorCode,
        string? errorMessage,
        string? traceId = null)
    {
        // 1. 规范状态值
        var normalizedStatus = NormalizeStatus(status);

        // 2. 生成异常状态
        return new PersonalModuleStatusDto
        {
            Module = module,
            Status = normalizedStatus,
            ErrorCode = errorCode,
            ErrorMessage = errorMessage,
            TraceId = traceId
        };
    }

    /// <summary>
    /// 计算总览整体状态。
    /// </summary>
    /// <param name="moduleStatuses">模块状态集合。</param>
    /// <param name="hasAnyData">是否存在可用数据。</param>
    /// <returns>overallStatus 值。</returns>
    public string ResolveOverallStatus(IReadOnlyCollection<PersonalModuleStatusDto> moduleStatuses, bool hasAnyData)
    {
        // 1. 无模块时按是否有数据判定
        if (moduleStatuses.Count == 0)
        {
            return hasAnyData ? "success" : "failure";
        }

        // 2. 全部成功直接返回 success
        var hasIssue = moduleStatuses.Any(static x => !string.Equals(x.Status, "ok", StringComparison.OrdinalIgnoreCase));
        if (!hasIssue)
        {
            return "success";
        }

        // 3. 存在降级时按可用数据判定
        return hasAnyData ? "partial_success" : "failure";
    }

    private static string NormalizeStatus(string status)
    {
        // 1. 空状态统一按 failed 处理
        if (string.IsNullOrWhiteSpace(status))
        {
            return "failed";
        }

        // 2. 限定可用状态值
        return status.ToLowerInvariant() switch
        {
            "ok" => "ok",
            "degraded" => "degraded",
            "failed" => "failed",
            "timeout" => "timeout",
            "skipped" => "skipped",
            _ => "failed"
        };
    }
}
