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

namespace Tiku.Api.Contracts;

/// <summary>
///     内容管理查询参数。
/// </summary>
public sealed class ContentManagementQueryDto
{
    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     内容入口 ID。
    /// </summary>
    public Guid? EntryId { get; set; }

    /// <summary>
    ///     节点 ID。
    /// </summary>
    public Guid? NodeId { get; set; }

    /// <summary>
    ///     题集 ID。
    /// </summary>
    public Guid? CollectionId { get; set; }

    /// <summary>
    ///     父节点 ID；传 root 表示根节点。
    /// </summary>
    [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; }

    /// <summary>
    ///     入口类型。
    /// </summary>
    [StringLength(50)]
    public string? EntryType { get; set; }

    /// <summary>
    ///     题集类型。
    /// </summary>
    [StringLength(50)]
    public string? CollectionType { get; set; }

    /// <summary>
    ///     模式。
    /// </summary>
    [StringLength(50)]
    public string? Mode { get; set; }

    /// <summary>
    ///     标记类型。
    /// </summary>
    [StringLength(50)]
    public string? MarkerType { get; set; }

    /// <summary>
    ///     关键字。
    /// </summary>
    [StringLength(100)]
    public string? Keyword { get; set; }

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

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [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);
    }
}

/// <summary>
///     新增或更新内容条目请求 DTO。
/// </summary>
public sealed class UpsertContentEntryDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

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

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    [StringLength(64)]
    public string? LegacyId { get; set; }

    /// <summary>
    ///     入口键。
    /// </summary>
    [StringLength(100)]
    public string? EntryKey { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(300)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     入口类型。
    /// </summary>
    [StringLength(50)]
    public string? EntryType { get; set; }

    /// <summary>
    ///     图标。
    /// </summary>
    [StringLength(100)]
    public string? Icon { get; set; }

    /// <summary>
    ///     路由地址。
    /// </summary>
    [StringLength(500)]
    public string? Route { get; set; }

    /// <summary>
    ///     说明。
    /// </summary>
    [StringLength(2000)]
    public string? Description { get; set; }

    /// <summary>
    ///     可见性。
    /// </summary>
    [StringLength(50)]
    public string? Visibility { get; set; }

    /// <summary>
    ///     访问规则。
    /// </summary>
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     布局配置。
    /// </summary>
    public JsonElement LayoutConfig { get; set; } = JsonDefaults.Object();

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

    /// <summary>
    ///     是否启用。
    /// </summary>
    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);
    }
}

/// <summary>
///     新增或更新内容节点请求 DTO。
/// </summary>
public sealed class UpsertContentNodeDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     内容入口 ID。
    /// </summary>
    [Required]
    public Guid EntryId { get; set; }

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

    /// <summary>
    ///     父节点 ID。
    /// </summary>
    public Guid? ParentId { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    [StringLength(64)]
    public string? LegacyId { get; set; }

    /// <summary>
    ///     节点键。
    /// </summary>
    [StringLength(100)]
    public string? NodeKey { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(300)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     节点Type。
    /// </summary>
    [StringLength(50)]
    public string? NodeType { get; set; }

    /// <summary>
    ///     标记类型。
    /// </summary>
    [StringLength(50)]
    public string? MarkerType { get; set; }

    /// <summary>
    ///     标记配置。
    /// </summary>
    public JsonElement MarkerConfig { get; set; } = JsonDefaults.Object();

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

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

    /// <summary>
    ///     是否可选择。
    /// </summary>
    public bool? IsSelectable { get; set; }

    /// <summary>
    ///     是否叶子节点。
    /// </summary>
    public bool? IsLeaf { get; set; }

    /// <summary>
    ///     访问规则。
    /// </summary>
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    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);
    }
}

/// <summary>
///     新增或更新题目题集请求 DTO。
/// </summary>
public sealed class UpsertQuestionCollectionDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

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

    /// <summary>
    ///     内容入口 ID。
    /// </summary>
    public Guid? EntryId { get; set; }

    /// <summary>
    ///     节点 ID。
    /// </summary>
    public Guid? NodeId { get; set; }

    /// <summary>
    ///     科目 ID。
    /// </summary>
    public Guid? SubjectId { get; set; }

    /// <summary>
    ///     分类 ID。
    /// </summary>
    public Guid? CategoryId { get; set; }

    /// <summary>
    ///     题库 ID。
    /// </summary>
    public Guid? QuestionBankId { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    [StringLength(64)]
    public string? LegacyId { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(300)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     题集类型。
    /// </summary>
    [StringLength(50)]
    public string? CollectionType { get; set; }

    /// <summary>
    ///     来源类型。
    /// </summary>
    [StringLength(50)]
    public string? SourceType { get; set; }

    /// <summary>
    ///     筛选条件。
    /// </summary>
    public JsonElement Filters { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     总分。
    /// </summary>
    public decimal? TotalScore { get; set; }

    /// <summary>
    ///     时长，单位为分钟。
    /// </summary>
    public int? DurationMinutes { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    [StringLength(50)]
    public string? Status { get; set; }

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

    /// <summary>
    ///     访问规则。
    /// </summary>
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    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);
    }
}

/// <summary>
///     题集题目请求 DTO。
/// </summary>
public sealed class CollectionQuestionDto
{
    /// <summary>
    ///     题目 ID。
    /// </summary>
    [Required]
    public Guid QuestionId { get; set; }

    /// <summary>
    ///     来源。
    /// </summary>
    [Required]
    public QuestionSource Source { get; set; } = QuestionSource.Tenant;

    /// <summary>
    ///     分段键。
    /// </summary>
    [StringLength(100)]
    public string? SectionKey { get; set; }

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

    /// <summary>
    ///     分数。
    /// </summary>
    public decimal? Score { get; set; }

    /// <summary>
    ///     是否必填。
    /// </summary>
    public bool? Required { get; set; }

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

    public CollectionQuestionCommand ToCommand()
    {
        return new CollectionQuestionCommand(
            new QuestionLocator(Source, QuestionId),
            SectionKey,
            Order,
            Score,
            Required,
            Metadata);
    }
}

/// <summary>
///     替换题集Items请求 DTO。
/// </summary>
public sealed class ReplaceCollectionItemsDto
{
    /// <summary>
    ///     题集 ID。
    /// </summary>
    [Required]
    public Guid CollectionId { get; set; }

    /// <summary>
    ///     题目列表。
    /// </summary>
    public IReadOnlyCollection<CollectionQuestionDto> Questions { get; set; } = [];

    public ReplaceCollectionItemsCommand ToCommand()
    {
        return new ReplaceCollectionItemsCommand(
            CollectionId,
            Questions.Select(question => question.ToCommand()).ToArray());
    }
}

/// <summary>
///     新增或更新练习Blueprint请求 DTO。
/// </summary>
public sealed class UpsertPracticeBlueprintDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

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

    /// <summary>
    ///     内容入口 ID。
    /// </summary>
    public Guid? EntryId { get; set; }

    /// <summary>
    ///     节点 ID。
    /// </summary>
    public Guid? NodeId { get; set; }

    /// <summary>
    ///     题集 ID。
    /// </summary>
    public Guid? CollectionId { get; set; }

    /// <summary>
    ///     历史系统 ID。
    /// </summary>
    [StringLength(64)]
    public string? LegacyId { get; set; }

    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(300)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     模式。
    /// </summary>
    [StringLength(50)]
    public string? Mode { get; set; }

    /// <summary>
    ///     组卷方式。
    /// </summary>
    [StringLength(50)]
    public string? AssemblyType { get; set; }

    /// <summary>
    ///     题目数量上限。
    /// </summary>
    public int? QuestionLimit { get; set; }

    /// <summary>
    ///     时长，单位为分钟。
    /// </summary>
    public int? DurationMinutes { get; set; }

    /// <summary>
    ///     总分。
    /// </summary>
    public decimal? TotalScore { get; set; }

    /// <summary>
    ///     及格分。
    /// </summary>
    public decimal? PassScore { get; set; }

    /// <summary>
    ///     分段配置。
    /// </summary>
    public JsonElement Sections { get; set; } = JsonDefaults.Array();

    /// <summary>
    ///     规则配置。
    /// </summary>
    public JsonElement Rules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     访问规则。
    /// </summary>
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     状态。
    /// </summary>
    [StringLength(50)]
    public string? Status { get; set; }

    /// <summary>
    ///     显示顺序。
    /// </summary>
    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);
    }
}

/// <summary>
///     导入Template查询参数。
/// </summary>
public sealed class ImportTemplateQueryDto
{
    /// <summary>
    ///     导入Type。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string ImportType { get; set; } = string.Empty;

    /// <summary>
    ///     导出格式。
    /// </summary>
    [StringLength(10)]
    public string? Format { get; set; }
}