<commit_before>﻿using System.Globalization;
using System.Text.Json;
using EFCore.NamingConventions.Internal;
using FilterLists.Directory.Domain.Aggregates;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;

public record Change
{
    public int Id { get; private init; }
    public string? Reason { get; private init; }
    public DateTime SubmittedAt { get; private init; }
    public DateTime? ApprovedAt { get; private init; }
    public DateTime? RejectedAt { get; private init; }
    public string? RejectedReason { get; private init; }
    public JsonDocument? AggregateBefore { get; private init; }
    public JsonDocument? AggregateAfter { get; private init; }
    public AggregateType? AggregateType { get; private init; }
    public int? FilterListId { get; private init; }
    public FilterList? FilterList { get; }
    public string? LanguageIso6391 { get; private init; }
    public Language? Language { get; }
    public int? LicenseId { get; private init; }
    public License? License { get; }
    public int? MaintainerId { get; private init; }
    public Maintainer? Maintainer { get; }
    public int? SoftwareId { get; private init; }
    public Software? Software { get; }
    public int? SyntaxId { get; private init; }
    public Syntax? Syntax { get; }
    public int? TagId { get; private init; }
    public Tag? Tag { get; }
}

internal class UpdateConfiguration : IEntityTypeConfiguration<Change>
{
    public virtual void Configure(EntityTypeBuilder<Change> builder)
    {
        builder.Property(c => c.SubmittedAt)
            .HasDefaultValueSql("CURRENT_TIMESTAMP");
        builder
            .Property(c => c.AggregateType)
            .HasComputedColumnSql(BuildComputedAggregateTypeSql(), true);

        static string BuildComputedAggregateTypeSql()
        {
            // TODO: register and resolve INameRewriter
            var nr = new SnakeCaseNameRewriter(CultureInfo.InvariantCulture);
            return $@"
                CASE 
                    WHEN {nr.RewriteName(nameof(Change.FilterListId))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.FilterList))}'::{nr.RewriteName(nameof(AggregateType))}
                    WHEN {nr.RewriteName(nameof(Change.LanguageIso6391))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.Language))}'::{nr.RewriteName(nameof(AggregateType))}
                    WHEN {nr.RewriteName(nameof(Change.LicenseId))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.License))}'::{nr.RewriteName(nameof(AggregateType))}<commit_msg>fix(dir): 🐛 convention-generated constraint name<commit_after>﻿using System.Globalization;
using System.Text.Json;
using EFCore.NamingConventions.Internal;
using FilterLists.Directory.Domain.Aggregates;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;

public record Change
{
    public int Id { get; private init; }
    public string? Reason { get; private init; }
    public DateTime SubmittedAt { get; private init; }
    public DateTime? ApprovedAt { get; private init; }
    public DateTime? RejectedAt { get; private init; }
    public string? RejectedReason { get; private init; }
    public JsonDocument? AggregateBefore { get; private init; }
    public JsonDocument? AggregateAfter { get; private init; }
    public AggregateType? AggregateType { get; private init; }
    public int? FilterListId { get; private init; }
    public FilterList? FilterList { get; }
    public string? LanguageIso6391 { get; private init; }
    public Language? Language { get; }
    public int? LicenseId { get; private init; }
    public License? License { get; }
    public int? MaintainerId { get; private init; }
    public Maintainer? Maintainer { get; }
    public int? SoftwareId { get; private init; }
    public Software? Software { get; }
    public int? SyntaxId { get; private init; }
    public Syntax? Syntax { get; }
    public int? TagId { get; private init; }
    public Tag? Tag { get; }
}

internal class UpdateConfiguration : IEntityTypeConfiguration<Change>
{
    public virtual void Configure(EntityTypeBuilder<Change> builder)
    {
        builder.Property(c => c.SubmittedAt)
            .HasDefaultValueSql("CURRENT_TIMESTAMP");
        builder
            .Property(c => c.AggregateType)
            .HasComputedColumnSql(BuildComputedAggregateTypeSql(), true);
        builder.HasOne(c => c.Language)
            .WithMany(l => l.Changes)
            .HasForeignKey(c => c.LanguageIso6391)
            .HasConstraintName("fk_changes_languages_language_iso6391");

        static string BuildComputedAggregateTypeSql()
        {
            // TODO: register and resolve INameRewriter
            var nr = new SnakeCaseNameRewriter(CultureInfo.InvariantCulture);
            return $@"
                CASE 
                    WHEN {nr.RewriteName(nameof(Change.FilterListId))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.FilterList))}'::{nr.RewriteName(nameof(AggregateType))}
                    WHEN {nr.RewriteName(nameof(Change.LanguageIso6391))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.Language))}'::{nr.RewriteName(nameof(AggregateType))}
                    WHEN {nr.RewriteName(nameof(Change.LicenseId))} IS NOT NULL THEN '{nr.RewriteName(nameof(AggregateType.License))}'::{nr.RewriteName(nameof(AggregateType))}
{'fraction_non_alphanumeric': 0.10095719703810728, 'fraction_numerical': 0.004334477153693336, 'mean_word_length': 3.550534100246508, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3961835', 'n_tokens_mistral': 1629, 'n_tokens_neox': 1565, 'n_words': 396}