using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Notifications;

namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Configurations;

/// <summary>
/// EF Core mapping for the central notification outbox entity. <see cref="Notification.TypeData"/>
/// and <see cref="Notification.ResolvedTargets"/> are intentionally left unconstrained
/// (nullable nvarchar(max)) as they carry variable-length JSON / target snapshots.
/// </summary>
public class NotificationOutboxConfiguration : IEntityTypeConfiguration<Notification>
{
    /// <summary>Configures the EF Core entity type mapping for <see cref="Notification"/>.</summary>
    /// <param name="builder">The entity type builder to configure.</param>
    public void Configure(EntityTypeBuilder<Notification> builder)
    {
        builder.HasKey(n => n.NotificationId);

        builder.Property(n => n.NotificationId).HasMaxLength(64);

        builder.Property(n => n.Type)
            .HasConversion<string>()
            .HasMaxLength(32)
            .IsRequired();

        builder.Property(n => n.Status)
            .HasConversion<string>()
            .HasMaxLength(32)
            .IsRequired();

        builder.Property(n => n.ListName)
            .HasMaxLength(200)
            .IsRequired();

        builder.Property(n => n.Subject)
            .HasMaxLength(1000)
            .IsRequired();

        builder.Property(n => n.Body).IsRequired();

        builder.Property(n => n.LastError).HasMaxLength(4000);

        builder.Property(n => n.SourceSiteId)
            .HasMaxLength(100)
            .IsRequired();

        builder.Property(n => n.SourceInstanceId).HasMaxLength(200);

        builder.Property(n => n.SourceScript).HasMaxLength(200);

        // SourceNode: node-local identifier of the
        // cluster member that produced the notification (e.g. "node-a", "central-a").
        // NULL is valid for rows that pre-date this feature. ASCII — varchar(64).
        // No index — KPIs are per-site on this table, not per-node; SourceNode is only
        // echoed onto NotifyDeliver audit rows for cross-row correlation.
        builder.Property(n => n.SourceNode)
            .HasColumnType("varchar(64)")
            .HasMaxLength(64)
            .IsUnicode(false);

        // OriginExecutionId: nullable uniqueidentifier carried from the
        // site so the dispatcher can echo it onto NotifyDeliver audit rows. No index —
        // it is never a query predicate on this table, only copied onto audit events.

        // OriginParentExecutionId: nullable uniqueidentifier carried from
        // the site — the routed run's parent ExecutionId — so the dispatcher can echo it
        // onto NotifyDeliver audit rows. No index — same rationale as OriginExecutionId.

        builder.HasIndex(n => new { n.Status, n.NextAttemptAt });

        builder.HasIndex(n => new { n.SourceSiteId, n.CreatedAt });

        // Covers ComputeKpisAsync's "DeliveredLastInterval" count
        // (Status == Delivered && DeliveredAt >= deliveredSince): filtered to just the
        // Delivered rows so the index stays small relative to the full table and the KPI
        // query can seek it directly instead of scanning every status (arch-review WP1.4).
        // Status is stored as its enum name (HasConversion<string>() above), so the filter
        // predicate matches on the literal 'Delivered', not the underlying int value.
        // No N'' prefix: the value is ASCII-only (fine on SQL Server's nvarchar column)
        // and the repository tests' SQLite provider rejects the T-SQL N'' national-string
        // literal syntax outright when EnsureCreated() runs this filter as DDL.
        builder.HasIndex(n => n.DeliveredAt)
            .HasDatabaseName("IX_Notifications_Delivered")
            .HasFilter("[Status] = 'Delivered'");
    }
}
