using System.ComponentModel.DataAnnotations; using System.Text.Json; using Tiku.Application.Content; using Tiku.Domain.Common; namespace Tiku.Api.Contracts; public sealed class ContentManagementQueryDto { public Guid? RegionId { get; set; } public Guid? EntryId { get; set; } public Guid? NodeId { get; set; } public Guid? CollectionId { get; set; } [StringLength(64)] [RegularExpression("^(root|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$")] public string? ParentId { get; set; } [StringLength(50)] public string? EntryType { get; set; } [StringLength(50)] public string? CollectionType { get; set; } [StringLength(50)] public string? Mode { get; set; } [StringLength(50)] public string? MarkerType { get; set; } [StringLength(100)] public string? Keyword { get; set; } public bool IncludeInactive { get; set; } [Range(1, 1000)] public int? Limit { get; set; } public ContentManagementFilter ToFilter() { return new ContentManagementFilter( RegionId, EntryId, NodeId, CollectionId, ParentId, EntryType, CollectionType, Mode, MarkerType, Keyword, IncludeInactive, Limit); } } public sealed class UpsertContentEntryDto { public Guid? Id { get; set; } public Guid? RegionId { get; set; } [StringLength(64)] public string? LegacyId { get; set; } [StringLength(100)] public string? EntryKey { get; set; } [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; [StringLength(50)] public string? EntryType { get; set; } [StringLength(100)] public string? Icon { get; set; } [StringLength(500)] public string? Route { get; set; } [StringLength(2000)] public string? Description { get; set; } [StringLength(50)] public string? Visibility { get; set; } public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); public JsonElement LayoutConfig { get; set; } = JsonDefaults.Object(); public int? Order { get; set; } public bool? IsActive { get; set; } public UpsertContentEntryCommand ToCommand() { return new UpsertContentEntryCommand( Id, RegionId, LegacyId, EntryKey, Name, EntryType, Icon, Route, Description, Visibility, AccessRules, LayoutConfig, Order, IsActive); } } public sealed class UpsertContentNodeDto { public Guid? Id { get; set; } [Required] public Guid EntryId { get; set; } public Guid? RegionId { get; set; } public Guid? ParentId { get; set; } [StringLength(64)] public string? LegacyId { get; set; } [StringLength(100)] public string? NodeKey { get; set; } [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; [StringLength(50)] public string? NodeType { get; set; } [StringLength(50)] public string? MarkerType { get; set; } public JsonElement MarkerConfig { get; set; } = JsonDefaults.Object(); public int? Order { get; set; } public bool? IsActive { get; set; } public bool? IsSelectable { get; set; } public bool? IsLeaf { get; set; } public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertContentNodeCommand ToCommand() { return new UpsertContentNodeCommand( Id, EntryId, RegionId, ParentId, LegacyId, NodeKey, Name, NodeType, MarkerType, MarkerConfig, Order, IsActive, IsSelectable, IsLeaf, AccessRules, Metadata); } } public sealed class UpsertQuestionCollectionDto { public Guid? Id { get; set; } public Guid? RegionId { get; set; } public Guid? EntryId { get; set; } public Guid? NodeId { get; set; } public Guid? SubjectId { get; set; } public Guid? CategoryId { get; set; } public Guid? QuestionBankId { get; set; } [StringLength(64)] public string? LegacyId { get; set; } [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; [StringLength(50)] public string? CollectionType { get; set; } [StringLength(50)] public string? SourceType { get; set; } public JsonElement Filters { get; set; } = JsonDefaults.Object(); public decimal? TotalScore { get; set; } public int? DurationMinutes { get; set; } [StringLength(50)] public string? Status { get; set; } public int? Order { get; set; } public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertQuestionCollectionCommand ToCommand() { return new UpsertQuestionCollectionCommand( Id, RegionId, EntryId, NodeId, SubjectId, CategoryId, QuestionBankId, LegacyId, Name, CollectionType, SourceType, Filters, TotalScore, DurationMinutes, Status, Order, AccessRules, Metadata); } } public sealed class CollectionQuestionDto { [Required] public Guid QuestionId { get; set; } [StringLength(100)] public string? SectionKey { get; set; } public int? Order { get; set; } public decimal? Score { get; set; } public bool? Required { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public CollectionQuestionCommand ToCommand() { return new CollectionQuestionCommand(QuestionId, SectionKey, Order, Score, Required, Metadata); } } public sealed class ReplaceCollectionItemsDto { [Required] public Guid CollectionId { get; set; } public IReadOnlyCollection Questions { get; set; } = []; public ReplaceCollectionItemsCommand ToCommand() { return new ReplaceCollectionItemsCommand( CollectionId, Questions.Select(question => question.ToCommand()).ToArray()); } } public sealed class UpsertPracticeBlueprintDto { public Guid? Id { get; set; } public Guid? RegionId { get; set; } public Guid? EntryId { get; set; } public Guid? NodeId { get; set; } public Guid? CollectionId { get; set; } [StringLength(64)] public string? LegacyId { get; set; } [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; [StringLength(50)] public string? Mode { get; set; } [StringLength(50)] public string? AssemblyType { get; set; } public int? QuestionLimit { get; set; } public int? DurationMinutes { get; set; } public decimal? TotalScore { get; set; } public decimal? PassScore { get; set; } public JsonElement Sections { get; set; } = JsonDefaults.Array(); public JsonElement Rules { get; set; } = JsonDefaults.Object(); public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); [StringLength(50)] public string? Status { get; set; } public int? Order { get; set; } public UpsertPracticeBlueprintCommand ToCommand() { return new UpsertPracticeBlueprintCommand( Id, RegionId, EntryId, NodeId, CollectionId, LegacyId, Name, Mode, AssemblyType, QuestionLimit, DurationMinutes, TotalScore, PassScore, Sections, Rules, AccessRules, Status, Order); } } public sealed class ImportTemplateQueryDto { [Required] [StringLength(50)] public string ImportType { get; set; } = string.Empty; [StringLength(10)] public string? Format { get; set; } }