using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.TenantAdmin;
using Tiku.Domain.Common;

namespace Tiku.Api.Contracts;

/// <summary>
///     租户管理端班级查询参数。
/// </summary>
public sealed class TenantAdminClassQueryDto
{
    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     关键字。
    /// </summary>
    public string? Keyword { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminClassFilter ToFilter()
    {
        return new TenantAdminClassFilter(RegionId, Status, Keyword, Limit);
    }
}

/// <summary>
///     租户管理端班级成员查询参数。
/// </summary>
public sealed class TenantAdminClassMemberQueryDto
{
    /// <summary>
    ///     班级 ID。
    /// </summary>
    [Required]
    public Guid ClassId { get; set; }

    /// <summary>
    ///     成员类型。
    /// </summary>
    public string? MemberType { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminClassMemberFilter ToFilter()
    {
        return new TenantAdminClassMemberFilter(ClassId, MemberType, Status, Limit);
    }
}

/// <summary>
///     租户管理端学生查询参数。
/// </summary>
public sealed class TenantAdminStudentQueryDto
{
    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     班级 ID。
    /// </summary>
    public Guid? ClassId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     关键字。
    /// </summary>
    public string? Keyword { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminStudentFilter ToFilter()
    {
        return new TenantAdminStudentFilter(RegionId, ClassId, Status, Keyword, Limit);
    }
}

/// <summary>
///     租户管理端学生活动查询参数。
/// </summary>
public sealed class TenantAdminStudentActivityQueryDto
{
    /// <summary>
    ///     学生用户 ID。
    /// </summary>
    public Guid? StudentUserId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminStudentActivityFilter ToFilter()
    {
        return new TenantAdminStudentActivityFilter(StudentUserId, Status, Limit);
    }
}

/// <summary>
///     租户管理端成员查询参数。
/// </summary>
public sealed class TenantAdminMemberQueryDto
{
    /// <summary>
    ///     角色。
    /// </summary>
    public string? Role { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     关键字。
    /// </summary>
    public string? Keyword { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminMemberFilter ToFilter()
    {
        return new TenantAdminMemberFilter(Role, Status, Keyword, Limit);
    }
}

/// <summary>
///     租户管理端审计日志查询参数。
/// </summary>
public sealed class TenantAdminAuditLogQueryDto
{
    /// <summary>
    ///     操作。
    /// </summary>
    public string? Action { get; set; }

    /// <summary>
    ///     目标类型。
    /// </summary>
    public string? TargetType { get; set; }

    /// <summary>
    ///     操作人用户 ID。
    /// </summary>
    public Guid? ActorUserId { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminAuditLogFilter ToFilter()
    {
        return new TenantAdminAuditLogFilter(Action, TargetType, ActorUserId, Limit);
    }
}

/// <summary>
///     租户管理端徽章查询参数。
/// </summary>
public sealed class TenantAdminBadgeQueryDto
{
    /// <summary>
    ///     分类。
    /// </summary>
    public string? Category { get; set; }

    /// <summary>
    ///     是否包含停用数据。
    /// </summary>
    public bool IncludeInactive { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminBadgeFilter ToFilter()
    {
        return new TenantAdminBadgeFilter(Category, IncludeInactive, Limit);
    }
}

/// <summary>
///     租户管理端徽章授予查询参数。
/// </summary>
public sealed class TenantAdminBadgeGrantQueryDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

    /// <summary>
    ///     徽章 ID。
    /// </summary>
    public Guid? BadgeId { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminBadgeGrantFilter ToFilter()
    {
        return new TenantAdminBadgeGrantFilter(UserId, BadgeId, Limit);
    }
}

/// <summary>
///     租户管理端通知查询参数。
/// </summary>
public sealed class TenantAdminNotificationQueryDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     通知类型。
    /// </summary>
    public string? NotificationType { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminNotificationFilter ToFilter()
    {
        return new TenantAdminNotificationFilter(UserId, Status, NotificationType, Limit);
    }
}

/// <summary>
///     租户管理端反馈查询参数。
/// </summary>
public sealed class TenantAdminFeedbackQueryDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     类型。
    /// </summary>
    public string? Type { get; set; }

    /// <summary>
    ///     关键字。
    /// </summary>
    public string? Keyword { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminFeedbackFilter ToFilter()
    {
        return new TenantAdminFeedbackFilter(UserId, Status, Type, Keyword, Limit);
    }
}

/// <summary>
///     新增或更新租户管理端班级请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminClassDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    public string? LegacyId { get; set; }

    /// <summary>
    ///     编码。
    /// </summary>
    public string? Code { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    public required string Name { get; set; }

    /// <summary>
    ///     说明。
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     显示顺序。
    /// </summary>
    public int? Order { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminClassCommand ToCommand()
    {
        return new UpsertTenantAdminClassCommand(Id, RegionId, LegacyId, Code, Name, Description, Status, Order,
            Metadata);
    }
}

/// <summary>
///     租户管理端用户查找请求 DTO。
/// </summary>
public sealed class TenantAdminUserLookupDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

    /// <summary>
    ///     用户名。
    /// </summary>
    public string? Username { get; set; }

    /// <summary>
    ///     邮箱。
    /// </summary>
    public string? Email { get; set; }

    /// <summary>
    ///     手机号。
    /// </summary>
    public string? Phone { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    public string? Name { get; set; }

    /// <summary>
    ///     头像地址。
    /// </summary>
    public string? AvatarUrl { get; set; }

    public UserLookupCommand ToCommand()
    {
        return new UserLookupCommand(UserId, Username, Email, Phone, Name, AvatarUrl);
    }
}

/// <summary>
///     新增或更新租户管理端班级成员请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminClassMemberDto
{
    /// <summary>
    ///     班级 ID。
    /// </summary>
    [Required]
    public Guid ClassId { get; set; }

    /// <summary>
    ///     用户信息。
    /// </summary>
    public TenantAdminUserLookupDto User { get; set; } = new();

    /// <summary>
    ///     成员类型。
    /// </summary>
    public string? MemberType { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminClassMemberCommand ToCommand()
    {
        return new UpsertTenantAdminClassMemberCommand(ClassId, User.ToCommand(), MemberType, Status, Metadata);
    }
}

/// <summary>
///     移除租户管理端班级成员请求 DTO。
/// </summary>
public sealed class RemoveTenantAdminClassMemberDto
{
    /// <summary>
    ///     班级成员 ID。
    /// </summary>
    [Required]
    public Guid ClassMemberId { get; set; }
}

/// <summary>
///     新增或更新租户管理端学生请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminStudentDto
{
    /// <summary>
    ///     用户信息。
    /// </summary>
    public TenantAdminUserLookupDto User { get; set; } = new();

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     已选择院校 ID。
    /// </summary>
    public Guid? SelectedSchoolId { get; set; }

    /// <summary>
    ///     已选择专业 ID。
    /// </summary>
    public Guid? SelectedMajorId { get; set; }

    /// <summary>
    ///     头像预设。
    /// </summary>
    public string? AvatarPreset { get; set; }

    /// <summary>
    ///     统计数据。
    /// </summary>
    public JsonElement Stats { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     进度数据。
    /// </summary>
    public JsonElement Progress { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     模块选择数据。
    /// </summary>
    public JsonElement ModuleSelections { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     原始用户资料。
    /// </summary>
    public JsonElement RawProfile { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentCommand ToCommand()
    {
        return new UpsertTenantAdminStudentCommand(
            User.ToCommand(),
            RegionId,
            SelectedSchoolId,
            SelectedMajorId,
            AvatarPreset,
            Stats,
            Progress,
            ModuleSelections,
            RawProfile);
    }
}

/// <summary>
///     更新租户管理端学生状态请求 DTO。
/// </summary>
public sealed class UpdateTenantAdminStudentStatusDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    [Required]
    public Guid UserId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     原因。
    /// </summary>
    public string? Reason { get; set; }

    public UpdateTenantAdminStudentStatusCommand ToCommand()
    {
        return new UpdateTenantAdminStudentStatusCommand(UserId, Status, Reason);
    }
}

/// <summary>
///     租户管理端学生导入行请求 DTO。
/// </summary>
public sealed class TenantAdminStudentImportRowDto
{
    /// <summary>
    ///     用户信息。
    /// </summary>
    public TenantAdminUserLookupDto User { get; set; } = new();

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     班级 ID。
    /// </summary>
    public Guid? ClassId { get; set; }

    /// <summary>
    ///     头像预设。
    /// </summary>
    public string? AvatarPreset { get; set; }

    /// <summary>
    ///     原始用户资料。
    /// </summary>
    public JsonElement RawProfile { get; set; } = JsonDefaults.Object();

    public TenantAdminStudentImportRowCommand ToCommand()
    {
        return new TenantAdminStudentImportRowCommand(User.ToCommand(), RegionId, ClassId, AvatarPreset, RawProfile);
    }
}

/// <summary>
///     租户管理端学生导入请求 DTO。
/// </summary>
public sealed class TenantAdminStudentImportDto
{
    /// <summary>
    ///     数据行列表。
    /// </summary>
    [Required]
    public IReadOnlyCollection<TenantAdminStudentImportRowDto> Rows { get; set; } = [];

    public TenantAdminStudentImportCommand ToCommand()
    {
        return new TenantAdminStudentImportCommand(Rows.Select(row => row.ToCommand()).ToArray());
    }
}

/// <summary>
///     租户管理端批量分配班级请求 DTO。
/// </summary>
public sealed class TenantAdminBulkAssignClassDto
{
    /// <summary>
    ///     班级 ID。
    /// </summary>
    [Required]
    public Guid ClassId { get; set; }

    /// <summary>
    ///     用户 ID 列表。
    /// </summary>
    [Required]
    public IReadOnlyCollection<Guid> UserIds { get; set; } = [];

    public TenantAdminBulkAssignClassCommand ToCommand()
    {
        return new TenantAdminBulkAssignClassCommand(ClassId, UserIds);
    }
}

/// <summary>
///     租户管理端批量状态请求 DTO。
/// </summary>
public sealed class TenantAdminBulkStatusDto
{
    /// <summary>
    ///     用户 ID 列表。
    /// </summary>
    [Required]
    public IReadOnlyCollection<Guid> UserIds { get; set; } = [];

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     原因。
    /// </summary>
    [StringLength(1000)]
    public string? Reason { get; set; }

    public TenantAdminBulkStatusCommand ToCommand()
    {
        return new TenantAdminBulkStatusCommand(UserIds, Status, Reason);
    }
}

/// <summary>
///     新增或更新租户督导规则请求 DTO。
/// </summary>
public sealed class UpsertTenantSupervisionRuleDto
{
    /// <summary>
    ///     编码。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string Code { get; set; } = string.Empty;

    /// <summary>
    ///     标题。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string Title { get; set; } = string.Empty;

    /// <summary>
    ///     是否启用。
    /// </summary>
    public bool Enabled { get; set; } = true;

    /// <summary>
    ///     未签到天数。
    /// </summary>
    [Range(0, 3650)]
    public int? DaysWithoutCheckIn { get; set; }

    /// <summary>
    ///     当天最大答题数。
    /// </summary>
    [Range(0, int.MaxValue)]
    public int? MaxQuestionsAnsweredToday { get; set; }

    /// <summary>
    ///     跟进类型。
    /// </summary>
    [StringLength(50)]
    public string? FollowupType { get; set; }

    /// <summary>
    ///     优先级。
    /// </summary>
    [StringLength(50)]
    public string? Priority { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantSupervisionRuleCommand ToCommand()
    {
        return new UpsertTenantSupervisionRuleCommand(
            Code,
            Title,
            Enabled,
            DaysWithoutCheckIn,
            MaxQuestionsAnsweredToday,
            FollowupType,
            Priority,
            Metadata);
    }
}

/// <summary>
///     租户督导生成请求 DTO。
/// </summary>
public sealed class TenantSupervisionGenerateDto
{
    /// <summary>
    ///     用户 ID 列表。
    /// </summary>
    public IReadOnlyCollection<Guid>? UserIds { get; set; }

    /// <summary>
    ///     分配处理人用户 ID。
    /// </summary>
    public Guid? AssignedToUserId { get; set; }

    /// <summary>
    ///     到期时间。
    /// </summary>
    public DateTimeOffset? DueAt { get; set; }

    public TenantSupervisionGenerateCommand ToCommand()
    {
        return new TenantSupervisionGenerateCommand(UserIds, AssignedToUserId, DueAt);
    }
}

/// <summary>
///     新增或更新租户管理端学生Note请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminStudentNoteDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     学生用户 ID。
    /// </summary>
    [Required]
    public Guid StudentUserId { get; set; }

    /// <summary>
    ///     备注类型。
    /// </summary>
    public string? NoteType { get; set; }

    /// <summary>
    ///     内容。
    /// </summary>
    public required string Content { get; set; }

    /// <summary>
    ///     可见性。
    /// </summary>
    public string? Visibility { get; set; }

    /// <summary>
    ///     是否置顶。
    /// </summary>
    public bool? IsPinned { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentNoteCommand ToCommand()
    {
        return new UpsertTenantAdminStudentNoteCommand(Id, StudentUserId, NoteType, Content, Visibility, IsPinned,
            Metadata);
    }
}

/// <summary>
///     新增或更新租户管理端学生跟进请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminStudentFollowupDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     学生用户 ID。
    /// </summary>
    [Required]
    public Guid StudentUserId { get; set; }

    /// <summary>
    ///     分配处理人用户 ID。
    /// </summary>
    public Guid? AssignedToUserId { get; set; }

    /// <summary>
    ///     班级 ID。
    /// </summary>
    public Guid? ClassId { get; set; }

    /// <summary>
    ///     标题。
    /// </summary>
    public required string Title { get; set; }

    /// <summary>
    ///     说明。
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    ///     跟进类型。
    /// </summary>
    public string? FollowupType { get; set; }

    /// <summary>
    ///     优先级。
    /// </summary>
    public string? Priority { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     到期时间。
    /// </summary>
    public DateTimeOffset? DueAt { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentFollowupCommand ToCommand()
    {
        return new UpsertTenantAdminStudentFollowupCommand(
            Id,
            StudentUserId,
            AssignedToUserId,
            ClassId,
            Title,
            Description,
            FollowupType,
            Priority,
            Status,
            DueAt,
            Metadata);
    }
}

/// <summary>
///     新增或更新租户管理端成员请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminMemberDto
{
    /// <summary>
    ///     成员关系 ID。
    /// </summary>
    public Guid? MembershipId { get; set; }

    /// <summary>
    ///     用户信息。
    /// </summary>
    public TenantAdminUserLookupDto User { get; set; } = new();

    /// <summary>
    ///     角色。
    /// </summary>
    public string? Role { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     主要角色。
    /// </summary>
    public string? PrimaryRole { get; set; }

    public UpsertTenantAdminMemberCommand ToCommand()
    {
        return new UpsertTenantAdminMemberCommand(MembershipId, User.ToCommand(), Role, Status, PrimaryRole);
    }
}

/// <summary>
///     禁用租户管理端成员请求 DTO。
/// </summary>
public sealed class DisableTenantAdminMemberDto
{
    /// <summary>
    ///     成员关系 ID。
    /// </summary>
    [Required]
    public Guid MembershipId { get; set; }
}

/// <summary>
///     新增或更新租户品牌请求 DTO。
/// </summary>
public sealed class UpsertTenantBrandingDto
{
    /// <summary>
    ///     品牌名称。
    /// </summary>
    public required string BrandName { get; set; }

    /// <summary>
    ///     品牌简称。
    /// </summary>
    public string? ShortName { get; set; }

    /// <summary>
    ///     品牌标语。
    /// </summary>
    public string? Slogan { get; set; }

    /// <summary>
    ///     机构名称。
    /// </summary>
    public string? OrganizationName { get; set; }

    /// <summary>
    ///     Logo 地址。
    /// </summary>
    public string? LogoUrl { get; set; }

    /// <summary>
    ///     站点图标地址。
    /// </summary>
    public string? FaviconUrl { get; set; }

    /// <summary>
    ///     客服微信。
    /// </summary>
    public string? ServiceWechat { get; set; }

    /// <summary>
    ///     客服账号名称。
    /// </summary>
    public string? ServiceAccountName { get; set; }

    public UpsertTenantBrandingCommand ToCommand()
    {
        return new UpsertTenantBrandingCommand(
            BrandName,
            ShortName,
            Slogan,
            OrganizationName,
            LogoUrl,
            FaviconUrl,
            ServiceWechat,
            ServiceAccountName);
    }
}

/// <summary>
///     新增或更新租户设置请求 DTO。
/// </summary>
public sealed class UpsertTenantSettingsDto
{
    /// <summary>
    ///     前端功能开关。
    /// </summary>
    public JsonElement FeatureFlags { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     管理端功能开关。
    /// </summary>
    public JsonElement AdminFeatureFlags { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     公开配置。
    /// </summary>
    public JsonElement PublicConfig { get; set; } = JsonDefaults.Object();

    public UpsertTenantSettingsCommand ToCommand()
    {
        return new UpsertTenantSettingsCommand(FeatureFlags, AdminFeatureFlags, PublicConfig);
    }
}

/// <summary>
///     预览租户主题请求 DTO。
/// </summary>
public sealed class PreviewTenantThemeDto
{
    /// <summary>
    ///     模板编码。
    /// </summary>
    public required string TemplateCode { get; set; }

    /// <summary>
    ///     主题配置。
    /// </summary>
    public JsonElement Theme { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     公开资源配置。
    /// </summary>
    public JsonElement PublicAssets { get; set; } = JsonDefaults.Object();

    public PreviewTenantThemeCommand ToCommand()
    {
        return new PreviewTenantThemeCommand(TemplateCode, Theme, PublicAssets);
    }
}

/// <summary>
///     发布租户主题请求 DTO。
/// </summary>
public sealed class PublishTenantThemeDto
{
    /// <summary>
    ///     是否使用草稿配置。
    /// </summary>
    public bool? UseDraft { get; set; }

    /// <summary>
    ///     模板编码。
    /// </summary>
    public string? TemplateCode { get; set; }

    /// <summary>
    ///     主题配置。
    /// </summary>
    public JsonElement Theme { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     公开资源配置。
    /// </summary>
    public JsonElement PublicAssets { get; set; } = JsonDefaults.Object();

    public PublishTenantThemeCommand ToCommand()
    {
        return new PublishTenantThemeCommand(UseDraft ?? true, TemplateCode, Theme, PublicAssets);
    }
}

/// <summary>
///     创建租户域名请求 DTO。
/// </summary>
public sealed class CreateTenantDomainDto
{
    /// <summary>
    ///     访问域名。
    /// </summary>
    public required string Host { get; set; }

    /// <summary>
    ///     域名类型。
    /// </summary>
    public string? DomainType { get; set; }

    /// <summary>
    ///     是否主域名。
    /// </summary>
    public bool IsPrimary { get; set; }

    public CreateTenantDomainCommand ToCommand()
    {
        return new CreateTenantDomainCommand(Host, DomainType, IsPrimary);
    }
}

/// <summary>
///     新增或更新租户身份源Provider请求 DTO。
/// </summary>
public sealed class UpsertTenantIdentityProviderDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    public required string Provider { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     显示名称。
    /// </summary>
    public string? DisplayName { get; set; }

    /// <summary>
    ///     密钥引用。
    /// </summary>
    public string? SecretRef { get; set; }

    /// <summary>
    ///     优先级。
    /// </summary>
    public int? Priority { get; set; }

    /// <summary>
    ///     公开配置内容。
    /// </summary>
    public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();

    public UpsertTenantIdentityProviderCommand ToCommand()
    {
        return new UpsertTenantIdentityProviderCommand(Provider, Status, DisplayName, SecretRef, Priority,
            ConfigPublic);
    }
}

/// <summary>
///     新增或更新租户管理端徽章请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminBadgeDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    public string? LegacyId { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    public required string Name { get; set; }

    /// <summary>
    ///     说明。
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    ///     分类。
    /// </summary>
    public string? Category { get; set; }

    /// <summary>
    ///     图标地址。
    /// </summary>
    public string? IconUrl { get; set; }

    /// <summary>
    ///     级别。
    /// </summary>
    public int? Level { get; set; }

    /// <summary>
    ///     解锁类型。
    /// </summary>
    public string? UnlockType { get; set; }

    /// <summary>
    ///     条件字段。
    /// </summary>
    public string? ConditionField { get; set; }

    /// <summary>
    ///     条件运算符。
    /// </summary>
    public string? ConditionOperator { get; set; }

    /// <summary>
    ///     条件值。
    /// </summary>
    public decimal? ConditionValue { get; set; }

    /// <summary>
    ///     条件扩展配置。
    /// </summary>
    public JsonElement ConditionExtra { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     显示顺序。
    /// </summary>
    public int? Order { get; set; }

    /// <summary>
    ///     是否启用。
    /// </summary>
    public bool? IsActive { get; set; }

    public UpsertTenantAdminBadgeCommand ToCommand()
    {
        return new UpsertTenantAdminBadgeCommand(
            Id,
            LegacyId,
            Name,
            Description,
            Category,
            IconUrl,
            Level,
            UnlockType,
            ConditionField,
            ConditionOperator,
            ConditionValue,
            ConditionExtra,
            Order,
            IsActive);
    }
}

/// <summary>
///     授予租户管理端徽章请求 DTO。
/// </summary>
public sealed class GrantTenantAdminBadgeDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    [Required]
    public Guid UserId { get; set; }

    /// <summary>
    ///     徽章 ID。
    /// </summary>
    [Required]
    public Guid BadgeId { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    public string? LegacyId { get; set; }

    /// <summary>
    ///     备注。
    /// </summary>
    public string? Note { get; set; }

    /// <summary>
    ///     授予时间。
    /// </summary>
    public DateTimeOffset? GrantedAt { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public GrantTenantAdminBadgeCommand ToCommand()
    {
        return new GrantTenantAdminBadgeCommand(UserId, BadgeId, LegacyId, Note, GrantedAt, Metadata);
    }
}

/// <summary>
///     新增或更新租户管理端通知请求 DTO。
/// </summary>
public sealed class UpsertTenantAdminNotificationDto
{
    /// <summary>
    ///     用户 ID。
    /// </summary>
    [Required]
    public Guid UserId { get; set; }

    /// <summary>
    ///     通知类型。
    /// </summary>
    public required string NotificationType { get; set; }

    /// <summary>
    ///     严重级别。
    /// </summary>
    public string? Severity { get; set; }

    /// <summary>
    ///     标题。
    /// </summary>
    public required string Title { get; set; }

    /// <summary>
    ///     消息内容。
    /// </summary>
    public required string Message { get; set; }

    /// <summary>
    ///     操作按钮文案。
    /// </summary>
    public string? ActionLabel { get; set; }

    /// <summary>
    ///     操作路径。
    /// </summary>
    public string? ActionPath { get; set; }

    /// <summary>
    ///     来源类型。
    /// </summary>
    public string? SourceType { get; set; }

    /// <summary>
    ///     来源 ID。
    /// </summary>
    public Guid? SourceId { get; set; }

    /// <summary>
    ///     去重键。
    /// </summary>
    public string? DedupeKey { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminNotificationCommand ToCommand()
    {
        return new UpsertTenantAdminNotificationCommand(
            UserId,
            NotificationType,
            Severity,
            Title,
            Message,
            ActionLabel,
            ActionPath,
            SourceType,
            SourceId,
            DedupeKey,
            Metadata);
    }
}

/// <summary>
///     更新租户管理端反馈请求 DTO。
/// </summary>
public sealed class UpdateTenantAdminFeedbackDto
{
    /// <summary>
    ///     反馈 ID。
    /// </summary>
    [Required]
    public Guid FeedbackId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    ///     优先级。
    /// </summary>
    public string? Priority { get; set; }

    /// <summary>
    ///     处理结果。
    /// </summary>
    public string? Resolution { get; set; }

    /// <summary>
    ///     备注。
    /// </summary>
    public string? Note { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpdateTenantAdminFeedbackCommand ToCommand()
    {
        return new UpdateTenantAdminFeedbackCommand(FeedbackId, Status, Priority, Resolution, Note, Metadata);
    }
}