using MiGu.Server.Configs;

namespace MiGu.Server.Auth;

/// <summary>
/// RBAC 角色。一个角色 = 一组「页面 + 操作码 + 控件可见性」授权，归属某个 scope。
/// <list type="bullet">
///   <item><see cref="Scope"/>：<c>Platform</c> / <c>RCSMonitor</c> / <c>*</c>（通用，对两个 scope 都生效）。</item>
///   <item><see cref="Pages"/>：可访问页面 Key 集合（见 <see cref="PageCatalog"/>）；含 <c>*</c> 表示该 scope 全部页面。</item>
///   <item><see cref="Ops"/>：细粒度操作码（如 <c>ops.car.pause</c>）；含 <c>*</c> 表示全部操作。</item>
///   <item><see cref="WidgetGrants"/>：控件级可见性（hidden / readonly / interactive）。</item>
///   <item><see cref="System"/>：内置系统角色，禁止删除（可改名/调权限但保底不被误删）。</item>
/// </list>
/// </summary>
public sealed class RbacRole
{
    public string Id { get; set; } = "";
    public string Name { get; set; } = "";
    public string Description { get; set; } = "";
    public string Scope { get; set; } = PageCatalog.ScopePlatform;
    public List<string> Pages { get; set; } = new();
    public List<string> Ops { get; set; } = new();
    public List<WidgetGrantDto> WidgetGrants { get; set; } = new();
    public bool System { get; set; }
}

/// <summary>
/// RBAC 用户。密码以 PBKDF2-SHA256 哈希存储（<see cref="Salt"/> / <see cref="PasswordHash"/> 均为 base64）。
/// 一个用户可拥有多个角色，其有效权限 = 当前 scope 下各角色授权的并集。
/// </summary>
public sealed class RbacUser
{
    public string Id { get; set; } = "";
    public string Username { get; set; } = "";
    public string DisplayName { get; set; } = "";
    public bool Enabled { get; set; } = true;
    public List<string> RoleIds { get; set; } = new();
    public string Salt { get; set; } = "";
    public string PasswordHash { get; set; } = "";
}

/// <summary>rbac.json 的根对象（内存 + 文件持久化）。</summary>
public sealed class RbacSnapshot
{
    public int Version { get; set; } = 1;
    public List<RbacRole> Roles { get; set; } = new();
    public List<RbacUser> Users { get; set; } = new();
}

// ─────────────────────────── API DTO ───────────────────────────

/// <summary>对外用户视图：绝不含 Salt / PasswordHash。<see cref="Scopes"/> 为该用户可登录的 scope 集合。</summary>
public sealed record RbacUserDto(
    string Id,
    string Username,
    string DisplayName,
    bool Enabled,
    List<string> RoleIds,
    List<string> Scopes);

public sealed record CreateUserRequest(
    string Username,
    string? DisplayName,
    string Password,
    List<string>? RoleIds,
    bool Enabled = true);

public sealed record UpdateUserRequest(
    string? DisplayName,
    List<string>? RoleIds,
    bool? Enabled);

public sealed record SetPasswordRequest(string Password);

public sealed record SaveRoleRequest(
    string? Id,
    string Name,
    string? Description,
    string Scope,
    List<string>? Pages,
    List<string>? Ops,
    List<WidgetGrantDto>? WidgetGrants);
