using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
{
    /// <inheritdoc />
    public partial class AddSiteIdToDataConnections : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            // Step 1: Drop old unique index on Name (allows duplicate names across sites)
            migrationBuilder.DropIndex(
                name: "IX_DataConnections_Name",
                table: "DataConnections");

            // Step 2: Add nullable SiteId column
            migrationBuilder.AddColumn<int>(
                name: "SiteId",
                table: "DataConnections",
                type: "int",
                nullable: true);

            // Step 3: Migrate data from SiteDataConnectionAssignments
            migrationBuilder.Sql(@"
                -- Phase A: Assign the first site to each existing DataConnection
                UPDATE dc
                SET dc.SiteId = a.SiteId
                FROM DataConnections dc
                INNER JOIN (
                    SELECT DataConnectionId, MIN(SiteId) AS SiteId
                    FROM SiteDataConnectionAssignments
                    GROUP BY DataConnectionId
                ) a ON dc.Id = a.DataConnectionId
                WHERE dc.SiteId IS NULL;

                -- Phase B: For connections assigned to additional sites, create copies
                -- and update InstanceConnectionBindings to point to the new copy
                DECLARE @AssignSiteId INT, @AssignConnId INT, @NewConnId INT;
                DECLARE @OrigName NVARCHAR(200), @OrigProtocol NVARCHAR(50), @OrigConfig NVARCHAR(4000);

                DECLARE assignment_cursor CURSOR FOR
                    SELECT a.SiteId, a.DataConnectionId
                    FROM SiteDataConnectionAssignments a
                    INNER JOIN DataConnections dc ON a.DataConnectionId = dc.Id
                    WHERE dc.SiteId <> a.SiteId;

                OPEN assignment_cursor;
                FETCH NEXT FROM assignment_cursor INTO @AssignSiteId, @AssignConnId;

                WHILE @@FETCH_STATUS = 0
                BEGIN
                    SELECT @OrigName = Name, @OrigProtocol = Protocol, @OrigConfig = Configuration
                    FROM DataConnections WHERE Id = @AssignConnId;

                    INSERT INTO DataConnections (SiteId, Name, Protocol, Configuration)
                    VALUES (@AssignSiteId, @OrigName, @OrigProtocol, @OrigConfig);

                    SET @NewConnId = SCOPE_IDENTITY();

                    -- Update bindings for instances on this site to point to the new connection
                    UPDATE icb
                    SET icb.DataConnectionId = @NewConnId
                    FROM InstanceConnectionBindings icb
                    INNER JOIN Instances i ON icb.InstanceId = i.Id
                    WHERE icb.DataConnectionId = @AssignConnId
                      AND i.SiteId = @AssignSiteId;

                    FETCH NEXT FROM assignment_cursor INTO @AssignSiteId, @AssignConnId;
                END

                CLOSE assignment_cursor;
                DEALLOCATE assignment_cursor;

                -- Phase C: Handle any DataConnections not assigned to any site
                -- (assign to the first site as a fallback)
                UPDATE dc
                SET dc.SiteId = (SELECT TOP 1 Id FROM Sites ORDER BY Id)
                FROM DataConnections dc
                WHERE dc.SiteId IS NULL;
            ");

            // Step 4: Make SiteId non-nullable
            migrationBuilder.AlterColumn<int>(
                name: "SiteId",
                table: "DataConnections",
                type: "int",
                nullable: false,
                defaultValue: 0,
                oldClrType: typeof(int),
                oldType: "int",
                oldNullable: true);

            // Step 5: Add composite unique index and FK
            migrationBuilder.CreateIndex(
                name: "IX_DataConnections_SiteId_Name",
                table: "DataConnections",
                columns: new[] { "SiteId", "Name" },
                unique: true);

            migrationBuilder.AddForeignKey(
                name: "FK_DataConnections_Sites_SiteId",
                table: "DataConnections",
                column: "SiteId",
                principalTable: "Sites",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            // Step 6: Drop SiteDataConnectionAssignments table
            migrationBuilder.DropTable(
                name: "SiteDataConnectionAssignments");
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            // Recreate SiteDataConnectionAssignments table
            migrationBuilder.CreateTable(
                name: "SiteDataConnectionAssignments",
                columns: table => new
                {
                    Id = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    DataConnectionId = table.Column<int>(type: "int", nullable: false),
                    SiteId = table.Column<int>(type: "int", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_SiteDataConnectionAssignments", x => x.Id);
                    table.ForeignKey(
                        name: "FK_SiteDataConnectionAssignments_DataConnections_DataConnectionId",
                        column: x => x.DataConnectionId,
                        principalTable: "DataConnections",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_SiteDataConnectionAssignments_Sites_SiteId",
                        column: x => x.SiteId,
                        principalTable: "Sites",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_SiteDataConnectionAssignments_DataConnectionId",
                table: "SiteDataConnectionAssignments",
                column: "DataConnectionId");

            migrationBuilder.CreateIndex(
                name: "IX_SiteDataConnectionAssignments_SiteId_DataConnectionId",
                table: "SiteDataConnectionAssignments",
                columns: new[] { "SiteId", "DataConnectionId" },
                unique: true);

            // Migrate data back
            migrationBuilder.Sql(@"
                INSERT INTO SiteDataConnectionAssignments (SiteId, DataConnectionId)
                SELECT SiteId, Id FROM DataConnections;
            ");

            // Remove FK and composite index
            migrationBuilder.DropForeignKey(
                name: "FK_DataConnections_Sites_SiteId",
                table: "DataConnections");

            migrationBuilder.DropIndex(
                name: "IX_DataConnections_SiteId_Name",
                table: "DataConnections");

            // Restore unique index on Name
            migrationBuilder.CreateIndex(
                name: "IX_DataConnections_Name",
                table: "DataConnections",
                column: "Name",
                unique: true);

            // Drop SiteId column
            migrationBuilder.DropColumn(
                name: "SiteId",
                table: "DataConnections");
        }
    }
}
