using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
{
    /// <summary>
    ///     Admin-008: adds <c>@ReleasedBy</c> parameter to
    ///     <c>dbo.sp_ReleaseExternalIdReservation</c> so the operator principal name (the LDAP
    ///     sign-in) is recorded in <c>ExternalIdReservation.ReleasedBy</c> and the
    ///     <c>ConfigAuditLog.Principal</c> column.
    ///
    ///     Prior to this migration the proc used <c>SUSER_SNAME()</c> for both columns, which
    ///     recorded the shared SQL service account rather than the Admin-UI operator who performed
    ///     the release — making the audit trail useless for attribution.  The stored proc now
    ///     accepts <c>@ReleasedBy nvarchar(128)</c> and uses it for both columns; validation
    ///     rejects a null/empty value the same way <c>@ReleaseReason</c> is validated.
    /// </summary>
    /// <inheritdoc />
    public partial class AddReleasedByToReleaseExternalIdReservation : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql(Procs.ReleaseExternalIdReservationV2);
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql(Procs.ReleaseExternalIdReservationV1);
        }

        private static class Procs
        {
            /// <summary>V2 — accepts <c>@ReleasedBy</c> for proper operator attribution.</summary>
            public const string ReleaseExternalIdReservationV2 = @"
CREATE OR ALTER PROCEDURE dbo.sp_ReleaseExternalIdReservation
    @Kind           nvarchar(16),
    @Value          nvarchar(64),
    @ReleaseReason  nvarchar(512),
    @ReleasedBy     nvarchar(128)
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    IF @ReleaseReason IS NULL OR LEN(@ReleaseReason) = 0
    BEGIN
        RAISERROR('ReleaseReason is required', 16, 1);
        RETURN;
    END

    IF @ReleasedBy IS NULL OR LEN(@ReleasedBy) = 0
    BEGIN
        RAISERROR('ReleasedBy is required', 16, 1);
        RETURN;
    END

    UPDATE dbo.ExternalIdReservation
    SET    ReleasedAt     = SYSUTCDATETIME(),
           ReleasedBy     = @ReleasedBy,
           ReleaseReason  = @ReleaseReason
    WHERE  Kind = @Kind AND Value = @Value AND ReleasedAt IS NULL;

    IF @@ROWCOUNT = 0
    BEGIN
        RAISERROR('No active reservation found for (%s, %s)', 16, 1, @Kind, @Value);
        RETURN;
    END

    -- Escape all caller-supplied values via STRING_ESCAPE so quotes/backslashes cannot break the
    -- JSON document or inject additional structure into the audit record.
    INSERT dbo.ConfigAuditLog (Principal, EventType, DetailsJson)
    VALUES (@ReleasedBy, 'ExternalIdReleased',
            CONCAT('{""kind"":""', STRING_ESCAPE(@Kind, 'json'),
                   '"",""value"":""', STRING_ESCAPE(@Value, 'json'), '""}'));
END
";

            /// <summary>V1 — original proc (uses SUSER_SNAME() for attribution). Restored on Down().</summary>
            public const string ReleaseExternalIdReservationV1 = @"
CREATE OR ALTER PROCEDURE dbo.sp_ReleaseExternalIdReservation
    @Kind           nvarchar(16),
    @Value          nvarchar(64),
    @ReleaseReason  nvarchar(512)
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    IF @ReleaseReason IS NULL OR LEN(@ReleaseReason) = 0
    BEGIN
        RAISERROR('ReleaseReason is required', 16, 1);
        RETURN;
    END

    UPDATE dbo.ExternalIdReservation
    SET    ReleasedAt     = SYSUTCDATETIME(),
           ReleasedBy     = SUSER_SNAME(),
           ReleaseReason  = @ReleaseReason
    WHERE  Kind = @Kind AND Value = @Value AND ReleasedAt IS NULL;

    IF @@ROWCOUNT = 0
    BEGIN
        RAISERROR('No active reservation found for (%s, %s)', 16, 1, @Kind, @Value);
        RETURN;
    END

    -- Escape both caller-supplied values via STRING_ESCAPE so quotes/backslashes cannot break the
    -- JSON document or inject additional structure into the audit record.
    INSERT dbo.ConfigAuditLog (Principal, EventType, DetailsJson)
    VALUES (SUSER_SNAME(), 'ExternalIdReleased',
            CONCAT('{""kind"":""', STRING_ESCAPE(@Kind, 'json'),
                   '"",""value"":""', STRING_ESCAPE(@Value, 'json'), '""}'));
END
";
        }
    }
}
