using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
{
    /// <inheritdoc />
    public partial class MigrateCompositionsToDerived : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            // Re-shape every pre-Phase-2 TemplateComposition so it points at a
            // newly created derived template ("<parent>.<slot>") that inherits
            // from the original base. Attribute and script rows are copied with
            // IsInherited=1; the composition's ComposedTemplateId is repointed.
            //
            // Idempotent: only rows whose target is still IsDerived=0 are touched.
            // Aborts the migration if any derived name would collide with an
            // existing template, so the operator can resolve manually.
            migrationBuilder.Sql(@"
SET NOCOUNT ON;

DECLARE @collisions NVARCHAR(MAX) = (
    SELECT STRING_AGG(owner.Name + N'.' + c.InstanceName, N', ')
    FROM TemplateCompositions c
    INNER JOIN Templates base_t ON base_t.Id = c.ComposedTemplateId
    INNER JOIN Templates owner ON owner.Id = c.TemplateId
    INNER JOIN Templates existing ON existing.Name = owner.Name + N'.' + c.InstanceName
    WHERE base_t.IsDerived = 0
);
IF @collisions IS NOT NULL
BEGIN
    DECLARE @msg NVARCHAR(MAX) =
        N'MigrateCompositionsToDerived: cannot create derived templates — these names already exist: '
        + @collisions
        + N'. Rename the conflicting templates and retry the migration.';
    THROW 50000, @msg, 1;
END

DECLARE @CompId INT, @BaseId INT, @OwnerName NVARCHAR(200), @SlotName NVARCHAR(200);
DECLARE @NewId INT, @NewName NVARCHAR(200);

DECLARE map_cursor CURSOR FAST_FORWARD FOR
    SELECT c.Id, c.ComposedTemplateId, owner.Name, c.InstanceName
    FROM TemplateCompositions c
    INNER JOIN Templates base_t ON base_t.Id = c.ComposedTemplateId
    INNER JOIN Templates owner ON owner.Id = c.TemplateId
    WHERE base_t.IsDerived = 0;

OPEN map_cursor;
FETCH NEXT FROM map_cursor INTO @CompId, @BaseId, @OwnerName, @SlotName;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @NewName = @OwnerName + N'.' + @SlotName;

    INSERT INTO Templates (Name, Description, ParentTemplateId, FolderId, IsDerived, OwnerCompositionId)
    SELECT @NewName, b.Description, b.Id, NULL, 1, @CompId
    FROM Templates b
    WHERE b.Id = @BaseId;

    SET @NewId = SCOPE_IDENTITY();

    INSERT INTO TemplateAttributes
        (TemplateId, Name, Value, DataType, IsLocked, Description, DataSourceReference, IsInherited, LockedInDerived)
    SELECT @NewId, a.Name, a.Value, a.DataType, a.IsLocked, a.Description, a.DataSourceReference, 1, 0
    FROM TemplateAttributes a
    WHERE a.TemplateId = @BaseId;

    INSERT INTO TemplateScripts
        (TemplateId, Name, Code, IsLocked, TriggerType, TriggerConfiguration, ParameterDefinitions, ReturnDefinition, MinTimeBetweenRuns, IsInherited, LockedInDerived)
    SELECT @NewId, s.Name, s.Code, s.IsLocked, s.TriggerType, s.TriggerConfiguration, s.ParameterDefinitions, s.ReturnDefinition, s.MinTimeBetweenRuns, 1, 0
    FROM TemplateScripts s
    WHERE s.TemplateId = @BaseId;

    UPDATE TemplateCompositions
    SET ComposedTemplateId = @NewId
    WHERE Id = @CompId;

    FETCH NEXT FROM map_cursor INTO @CompId, @BaseId, @OwnerName, @SlotName;
END

CLOSE map_cursor;
DEALLOCATE map_cursor;
");
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            // Reverse: repoint each composition back to the derived template's
            // base, then drop the derived templates (with their copied rows).
            migrationBuilder.Sql(@"
SET NOCOUNT ON;

UPDATE c
SET c.ComposedTemplateId = d.ParentTemplateId
FROM TemplateCompositions c
INNER JOIN Templates d ON d.Id = c.ComposedTemplateId
WHERE d.IsDerived = 1
  AND d.OwnerCompositionId = c.Id
  AND d.ParentTemplateId IS NOT NULL;

DELETE a FROM TemplateAttributes a
INNER JOIN Templates t ON t.Id = a.TemplateId
WHERE t.IsDerived = 1;

DELETE s FROM TemplateScripts s
INNER JOIN Templates t ON t.Id = s.TemplateId
WHERE t.IsDerived = 1;

DELETE FROM Templates WHERE IsDerived = 1;
");
        }
    }
}
