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

namespace Tiku.Api.Contracts;

public sealed class DirectContentQueryDto
{
    public Guid? RegionId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public Guid? ParentId { get; set; }
    public Guid? SubjectId { get; set; }
    public Guid? ChapterId { get; set; }
    public Guid? UnitId { get; set; }
    public Guid? SchoolId { get; set; }
    public Guid? MajorId { get; set; }
    public Guid? QuestionId { get; set; }

    [StringLength(50)]
    public string? Status { get; set; }

    [StringLength(200)]
    public string? Keyword { get; set; }

    [Range(1900, 3000)]
    public int? Year { get; set; }

    [Range(1, 1000)]
    public int? Limit { get; set; }

    public AdminLimitFilter ToFilter()
    {
        return new AdminLimitFilter(
            RegionId,
            EntryId,
            ContentNodeId,
            ParentId,
            SubjectId,
            ChapterId,
            UnitId,
            SchoolId,
            MajorId,
            QuestionId,
            Status,
            Keyword,
            Year,
            Limit);
    }
}

public sealed class DirectQuestionWriteDto
{
    public Guid? QuestionId { get; set; }
    public Guid? QuestionBankId { get; set; }
    public Guid? SubjectId { get; set; }
    public Guid? CategoryId { get; set; }
    public Guid? NodeId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public Guid? PrimaryCollectionId { get; set; }
    public string? LegacyId { get; set; }
    public string? Type { get; set; }
    public string? TypeLabel { get; set; }

    [Range(1, 5)]
    public int? Difficulty { get; set; }

    public JsonElement Tags { get; set; } = JsonDefaults.Array();
    public string? Content { get; set; }
    public JsonElement Options { get; set; } = JsonDefaults.Array();
    public int? CorrectOptionIndex { get; set; }
    public JsonElement CorrectOptionIndices { get; set; } = JsonDefaults.Array();
    public string? AnswerText { get; set; }
    public string? Explanation { get; set; }
    public JsonElement SubQuestions { get; set; } = JsonDefaults.Array();
    public string? CodeLang { get; set; }
    public string? CodeTemplate { get; set; }
    public string? MediaUrl { get; set; }
    public string? Status { get; set; }
    public JsonElement ExamMarkers { get; set; } = JsonDefaults.Object();
    public string? SourceHash { get; set; }
    public bool? CreateVersion { get; set; }

    public QuestionWriteCommand ToCommand(bool createVersionDefault)
    {
        return new QuestionWriteCommand(
            QuestionId,
            QuestionBankId,
            SubjectId,
            CategoryId,
            NodeId,
            EntryId,
            ContentNodeId,
            PrimaryCollectionId,
            LegacyId,
            Type,
            TypeLabel,
            Difficulty,
            Tags,
            Content,
            Options,
            CorrectOptionIndex,
            CorrectOptionIndices,
            AnswerText,
            Explanation,
            SubQuestions,
            CodeLang,
            CodeTemplate,
            MediaUrl,
            Status,
            ExamMarkers,
            SourceHash,
            CreateVersion ?? createVersionDefault);
    }
}

public sealed class DirectVocabularyUnitDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? Description { get; set; }
    public int? WordCount { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public VocabularyUnitCommand ToCommand()
    {
        return new VocabularyUnitCommand(Id, RegionId, EntryId, ContentNodeId, LegacyId, Name, Description, WordCount, Order, IsActive, Metadata);
    }
}

public sealed class DirectVocabularyWordDto
{
    public Guid? Id { get; set; }
    public Guid? UnitId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public required string Word { get; set; }
    public string? Phonetic { get; set; }
    public string? Meaning { get; set; }
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }
    public int? Difficulty { get; set; }
    public JsonElement Tags { get; set; } = JsonDefaults.Array();
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public VocabularyWordCommand ToCommand()
    {
        return new VocabularyWordCommand(
            Id,
            UnitId,
            EntryId,
            ContentNodeId,
            LegacyId,
            Word,
            Phonetic,
            Meaning,
            Example,
            ExampleTranslation,
            Difficulty,
            Tags,
            Order,
            IsActive,
            Metadata);
    }
}

public sealed class DirectHandbookSubjectDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? SchoolId { get; set; }
    public Guid? MajorId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? Type { get; set; }
    public string? Icon { get; set; }
    public string? Color { get; set; }
    public string? Description { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public HandbookSubjectCommand ToCommand()
    {
        return new HandbookSubjectCommand(
            Id,
            RegionId,
            SchoolId,
            MajorId,
            EntryId,
            ContentNodeId,
            LegacyId,
            Name,
            Type,
            Icon,
            Color,
            Description,
            Order,
            IsActive,
            Metadata);
    }
}

public sealed class DirectHandbookChapterDto
{
    public Guid? Id { get; set; }
    public Guid? SubjectId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? Description { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public HandbookChapterCommand ToCommand()
    {
        return new HandbookChapterCommand(Id, SubjectId, EntryId, ContentNodeId, LegacyId, Name, Description, Order, IsActive, Metadata);
    }
}

public sealed class DirectHandbookEntryDto
{
    public Guid? Id { get; set; }
    public Guid? ChapterId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public required string Title { get; set; }
    public string? Summary { get; set; }
    public string? Content { get; set; }
    public JsonElement Tags { get; set; } = JsonDefaults.Array();
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public HandbookEntryCommand ToCommand()
    {
        return new HandbookEntryCommand(Id, ChapterId, EntryId, ContentNodeId, LegacyId, Title, Summary, Content, Tags, Order, IsActive, Metadata);
    }
}

public sealed class DirectSchoolDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? ProfessionalExamDate { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public SchoolCommand ToCommand()
    {
        return new SchoolCommand(Id, RegionId, LegacyId, Name, ProfessionalExamDate, Metadata);
    }
}

public sealed class DirectMajorDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? SchoolId { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? Description { get; set; }
    public string? StudyTips { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }

    public MajorCommand ToCommand()
    {
        return new MajorCommand(Id, RegionId, SchoolId, LegacyId, Name, Description, StudyTips, Order, IsActive);
    }
}

public sealed class DirectScorelineFieldDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public required string FieldKey { get; set; }
    public required string FieldName { get; set; }
    public string? FieldType { get; set; }
    public string? Unit { get; set; }
    public bool? IsFilter { get; set; }
    public bool? IsRequired { get; set; }
    public bool? IsVisible { get; set; }
    public bool? IsTrend { get; set; }
    public JsonElement Options { get; set; } = JsonDefaults.Array();
    public string? Placeholder { get; set; }
    public string? Description { get; set; }
    public int? Order { get; set; }

    public ScorelineFieldCommand ToCommand()
    {
        return new ScorelineFieldCommand(
            Id,
            RegionId,
            LegacyId,
            FieldKey,
            FieldName,
            FieldType,
            Unit,
            IsFilter,
            IsRequired,
            IsVisible,
            IsTrend,
            Options,
            Placeholder,
            Description,
            Order);
    }
}

public sealed class DirectScorelineRecordDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? SchoolId { get; set; }
    public Guid? MajorId { get; set; }
    public string? LegacyId { get; set; }

    [Range(1900, 3000)]
    public int Year { get; set; }

    public string? SchoolName { get; set; }
    public string? MajorName { get; set; }
    public JsonElement FieldValues { get; set; } = JsonDefaults.Object();

    public ScorelineRecordCommand ToCommand()
    {
        return new ScorelineRecordCommand(
            Id,
            RegionId,
            SchoolId,
            MajorId,
            LegacyId,
            Year,
            SchoolName,
            MajorName,
            FieldValues);
    }
}

public sealed class DirectVideoDto
{
    public Guid? Id { get; set; }
    public Guid? SubjectId { get; set; }
    public string? LegacyId { get; set; }
    public required string Title { get; set; }
    public string? Description { get; set; }
    public string? VideoUrl { get; set; }
    public string? ThumbnailUrl { get; set; }
    public int? DurationSeconds { get; set; }
    public JsonElement KnowledgeTags { get; set; } = JsonDefaults.Array();
    public bool? IsGeneral { get; set; }
    public int? Difficulty { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public VideoExplanationCommand ToCommand()
    {
        return new VideoExplanationCommand(
            Id,
            SubjectId,
            LegacyId,
            Title,
            Description,
            VideoUrl,
            ThumbnailUrl,
            DurationSeconds,
            KnowledgeTags,
            IsGeneral,
            Difficulty,
            Order,
            IsActive,
            Metadata);
    }
}

public sealed class DirectQuestionVideoDto
{
    public Guid QuestionId { get; set; }
    public Guid VideoId { get; set; }
    public string? LegacyId { get; set; }
    public string? VideoType { get; set; }
    public int? Order { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public QuestionVideoCommand ToCommand()
    {
        return new QuestionVideoCommand(QuestionId, VideoId, LegacyId, VideoType, Order, Metadata);
    }
}

public sealed class DirectOperationContentDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? SchoolId { get; set; }
    public string? LegacyId { get; set; }
    public string? Title { get; set; }
    public string? Subtitle { get; set; }
    public string? Content { get; set; }
    public string? Question { get; set; }
    public string? Answer { get; set; }
    public string? Link { get; set; }
    public string? ButtonText { get; set; }
    public string? ButtonLink { get; set; }
    public string? BackgroundColor { get; set; }
    public string? BorderColor { get; set; }
    public string? ExamName { get; set; }
    public DateTimeOffset? ExamAt { get; set; }
    public string? ExamType { get; set; }
    public string? Description { get; set; }
    public int? Order { get; set; }
    public bool? IsActive { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public OperationContentCommand ToCommand()
    {
        return new OperationContentCommand(
            Id,
            RegionId,
            SchoolId,
            LegacyId,
            Title,
            Subtitle,
            Content,
            Question,
            Answer,
            Link,
            ButtonText,
            ButtonLink,
            BackgroundColor,
            BorderColor,
            ExamName,
            ExamAt,
            ExamType,
            Description,
            Order,
            IsActive,
            Metadata);
    }
}

public sealed class DirectImportDto
{
    public string? SourceFormat { get; set; }
    public string? SourceName { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? EntryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public Guid? SubjectId { get; set; }
    public Guid? CategoryId { get; set; }
    public Guid? QuestionBankId { get; set; }
    public Guid? CollectionId { get; set; }
    public bool? Async { get; set; }
    public IReadOnlyCollection<JsonElement>? Items { get; set; }
    public IReadOnlyCollection<JsonElement>? Units { get; set; }
    public IReadOnlyCollection<JsonElement>? Words { get; set; }
    public IReadOnlyCollection<JsonElement>? Subjects { get; set; }
    public IReadOnlyCollection<JsonElement>? Entries { get; set; }
    public IReadOnlyCollection<JsonElement>? Fields { get; set; }
    public IReadOnlyCollection<JsonElement>? Schools { get; set; }
    public IReadOnlyCollection<JsonElement>? Majors { get; set; }
    public IReadOnlyCollection<JsonElement>? Records { get; set; }
    public IReadOnlyCollection<JsonElement>? Videos { get; set; }

    public SimpleImportCommand ToCommand(string importType, bool dryRun)
    {
        return new SimpleImportCommand(
            importType,
            SourceFormat,
            SourceName,
            RegionId,
            EntryId,
            ContentNodeId,
            SubjectId,
            CategoryId,
            QuestionBankId,
            CollectionId,
            ResolveItems(importType),
            dryRun);
    }

    private IReadOnlyCollection<JsonElement> ResolveItems(string importType)
    {
        return importType.ToLowerInvariant() switch
        {
            "questions" => Items ?? [],
            "vocabulary" => Words ?? Units ?? Items ?? [],
            "handbook" => Entries ?? Subjects ?? Items ?? [],
            "scoreline" => Records ?? Schools ?? Majors ?? Fields ?? Items ?? [],
            "videos" => Videos ?? Items ?? [],
            _ => Items ?? []
        };
    }
}

public sealed class DirectImportJobDto
{
    public Guid JobId { get; set; }
}
