namespace MiGu.Server.Configs;

/// <summary>
/// 配置向导「可选项目录」与「选型 → 平台能力」映射的单一事实来源。
///
/// <para>前端向导从 <c>GET /api/wizard/options</c> 拿到这些可选项渲染勾选框；后端
/// <see cref="ModuleToPages"/> 在「按选型裁剪菜单」时把模块
/// 映射为 PageCatalog 的可见页 id。集中定义，避免前后端各写一份导致漂移。</para>
/// </summary>
public static class DeploymentCatalog
{
    /// <summary>一个可勾选项。<see cref="Id"/> 是稳定机器标识，<see cref="Group"/> 用于前端分组展示。</summary>
    public record Option(string Id, string Name, string Group, string Description);

    /// <summary>导航方式（多选，一等维度）。id 与 <see cref="DeploymentProfile.NavKindToSceneId"/> 的 key 对齐。</summary>
    public static readonly IReadOnlyList<Option> NavigationKinds = new[]
    {
        new Option("magnetic", "磁导航", "navigation", "磁条循迹 + 地标 / RFID 定位"),
        new Option("qrcode", "二维码导航", "navigation", "二维码地标 + 码值地图"),
        new Option("laser", "激光导航", "navigation", "反光板 / SLAM + 激光避障"),
    };

    /// <summary>功能模块（多选）。暂定保留 WMS / PTL 两项，后续按需扩展（参考 RIOT 的 WMS/WCS/MES/APS 分层）。</summary>
    public static readonly IReadOnlyList<Option> Modules = new[]
    {
        new Option("wms", "WMS 仓储管理", "module", "库位 / 库存 / 出入库管理"),
        new Option("ptl", "PTL 拣选系统", "module", "Pick-to-Light 亮灯拣选与播种"),
    };

    /// <summary>
    /// 功能模块 → PageCatalog 页面 Key 列表的映射。PTL 暂无专属配置页，未纳入映射（选中不影响菜单）。
    /// 注意：Key 必须是 PageCatalog 当前有效 Key（不能用 LegacyKeyAliases 里的旧名，否则裁剪悄然失效）。
    /// </summary>
    public static readonly IReadOnlyDictionary<string, string[]> ModuleToPages =
        new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
        {
            ["wms"] = new[] { "admin-config-facility", "admin-config-warehouse" },
        };

    /// <summary>所有「可被选型控制」的页面 Key（Module → 页 映射值的并集）。</summary>
    public static IReadOnlyCollection<string> TailorablePages()
    {
        var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        foreach (var v in ModuleToPages.Values) foreach (var p in v) set.Add(p);
        return set;
    }

    /// <summary>当前部署画像下被「点亮」的可裁剪页（已启用 Module 映射到的页）。</summary>
    public static IReadOnlyCollection<string> EnabledPages(DeploymentProfile dp)
    {
        var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        if (dp == null) return set;
        foreach (var m in dp.Modules ?? new List<string>())
            if (ModuleToPages.TryGetValue(m, out var ps)) foreach (var p in ps) set.Add(p);
        return set;
    }

    /// <summary>当前部署画像下应隐藏的页（可裁剪但未被点亮）。向导未完成（Configured=false）则不隐藏任何页。</summary>
    public static IReadOnlyCollection<string> HiddenPages(DeploymentProfile dp)
    {
        if (dp == null || !dp.Configured) return Array.Empty<string>();
        var enabled = EnabledPages(dp);
        return TailorablePages().Where(p => !enabled.Contains(p)).ToList();
    }

    /// <summary>
    /// 从 RBAC 计算出的可见页集合中移除「被部署画像隐藏」的页 —— 这是「按选型裁剪菜单」的核心。
    /// 不在任何映射中的页不受影响；向导未完成时原样返回（避免首登空菜单）。
    /// </summary>
    public static List<string> FilterPagesByDeployment(IEnumerable<string> pages, DeploymentProfile dp)
    {
        var input = (pages ?? Enumerable.Empty<string>()).ToList();
        if (dp == null || !dp.Configured) return input;
        var hidden = new HashSet<string>(HiddenPages(dp), StringComparer.OrdinalIgnoreCase);
        return input.Where(p => !hidden.Contains(p)).ToList();
    }
}
