/** PROMPT

Table interiors has the following columns:
- id INTEGER
- room_id INTEGER (NULLABLE)
- position INTEGER

Create a migration that finds all print groups that matches the following criterias:
- Has a room_id that is not null ON position 0
- Has one or more entries where room_id is NULL

Here is how the migration should work:
- Get the entry with the lowest position where room_id is NULL and set its position to 0.
- Set the position of the entry with room_id not null to the value of the row above.
- Two or more entries with room_id NULL can have the same position, in that case, use any of those entries.
- All entries in the group should then increase in a straight series starting from 1, except the entry that got position 0.
- Solve this by using a cursor

Entries with the same print_id are grouped together in a "print group".

*/



-- Migration to reposition interiors entries within print groups
-- Swaps position 0 entry (room_id NOT NULL) with lowest positioned NULL room_id entry
-- Then renumbers all remaining entries sequentially starting from 1

DO $$
DECLARE
    cursor_print_groups CURSOR FOR
        SELECT DISTINCT print_id
        FROM interiors
        WHERE print_id IN (
            -- Find print_ids that have both:
            -- 1. An entry with room_id NOT NULL at position 0
            -- 2. One or more entries with room_id NULL
            SELECT print_id
            FROM interiors
            WHERE room_id IS NOT NULL AND position = 0
            INTERSECT
            SELECT print_id
            FROM interiors
            WHERE room_id IS NULL
        )
        AND print_id IN (
            SELECT printid FROM "product-printproducts" WHERE groupid IN (1, 3)
        );

    current_print_id INTEGER;
    entry_at_position_0_id INTEGER;
    entry_at_position_0_old_pos INTEGER;
    lowest_null_entry_id INTEGER;
    lowest_null_position INTEGER;
    renumber_cursor CURSOR (p_print_id INTEGER, exclude_id INTEGER) FOR
        SELECT id
        FROM interiors
        WHERE print_id = p_print_id
          AND id != exclude_id
        ORDER BY
            CASE WHEN room_id IS NULL THEN position ELSE position END ASC,
            id ASC;

    counter INTEGER;
    entry_id INTEGER;
BEGIN
    -- Process each qualifying print group
    FOR print_group IN cursor_print_groups
    LOOP
        current_print_id := print_group.print_id;

        RAISE NOTICE 'Processing print_id: %', current_print_id;

        -- Get the entry currently at position 0 (room_id NOT NULL)
        SELECT id, position INTO entry_at_position_0_id, entry_at_position_0_old_pos
        FROM interiors
        WHERE print_id = current_print_id
          AND room_id IS NOT NULL
          AND position = 0
        LIMIT 1;

        -- Get the entry with lowest position where room_id IS NULL
        SELECT id, position INTO lowest_null_entry_id, lowest_null_position
        FROM interiors
        WHERE print_id = current_print_id
          AND room_id IS NULL
        ORDER BY position ASC, id ASC
        LIMIT 1;

        RAISE NOTICE 'Found entry at position 0: id=%, position=%',
            entry_at_position_0_id, entry_at_position_0_old_pos;
        RAISE NOTICE 'Found lowest NULL entry: id=%, position=%',
            lowest_null_entry_id, lowest_null_position;

        -- Step 1: Set the NULL entry to position 0
        UPDATE interiors
        SET position = 0
        WHERE id = lowest_null_entry_id;

        RAISE NOTICE 'Set entry id=% to position 0', lowest_null_entry_id;

        -- Step 2: Set the former position-0 entry to the old position of the NULL entry
        UPDATE interiors
        SET position = lowest_null_position
        WHERE id = entry_at_position_0_id;

        RAISE NOTICE 'Set entry id=% to position %', entry_at_position_0_id, lowest_null_position;

        -- Step 3: Renumber all other entries sequentially starting from 1
        counter := 1;

        OPEN renumber_cursor(current_print_id, lowest_null_entry_id);
        LOOP
            FETCH renumber_cursor INTO entry_id;
            EXIT WHEN NOT FOUND;

            UPDATE interiors
            SET position = counter
            WHERE id = entry_id;

            RAISE NOTICE 'Renumbered entry id=% to position %', entry_id, counter;
            counter := counter + 1;
        END LOOP;
        CLOSE renumber_cursor;

    END LOOP;

    RAISE NOTICE 'Migration completed successfully';
END $$;
