<?php
use Index\Db\DbConnection;
use Index\Db\Migration\DbMigration;

final class MakeOauthStuffBigint_20250423_224653 implements DbMigration {
    public function migrate(DbConnection $conn): void {
        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_scopes
                DROP FOREIGN KEY apps_scopes_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_scopes
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_uris
                DROP FOREIGN KEY apps_uris_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_uris
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NOT NULL AFTER uri_id;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_access
                DROP FOREIGN KEY oauth2_access_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_access
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NULL DEFAULT NULL AFTER acc_id;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                DROP FOREIGN KEY oauth2_authorise_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                DROP FOREIGN KEY oauth2_authorise_uri_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NOT NULL AFTER auth_id,
                CHANGE COLUMN uri_id uri_id BIGINT UNSIGNED NOT NULL AFTER user_id;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_device
                DROP FOREIGN KEY oauth2_device_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_device
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NOT NULL AFTER dev_id;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_refresh
                DROP FOREIGN KEY oauth2_refresh_app_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_refresh
                DROP FOREIGN KEY oauth2_refresh_access_foreign;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_refresh
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NULL DEFAULT NULL AFTER ref_id,
                CHANGE COLUMN acc_id acc_id BIGINT UNSIGNED NULL DEFAULT NULL AFTER user_id;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_apps
                CHANGE COLUMN app_id app_id BIGINT UNSIGNED NOT NULL FIRST,
                DROP COLUMN app_client_id,
                DROP INDEX apps_client_id_unique;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_uris
                CHANGE COLUMN uri_id uri_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_access
                CHANGE COLUMN acc_id acc_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                CHANGE COLUMN auth_id auth_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_device
                CHANGE COLUMN dev_id dev_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_refresh
                CHANGE COLUMN ref_id ref_id BIGINT UNSIGNED NOT NULL FIRST;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_scopes
                ADD CONSTRAINT apps_scopes_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_apps_uris
                ADD CONSTRAINT apps_uris_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_access
                ADD CONSTRAINT oauth2_access_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                ADD CONSTRAINT oauth2_authorise_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);
        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_authorise
                ADD CONSTRAINT oauth2_authorise_uri_foreign
                FOREIGN KEY (uri_id)
                REFERENCES msz_apps_uris (uri_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_device
                ADD CONSTRAINT oauth2_device_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $conn->execute(<<<SQL
            ALTER TABLE msz_oauth2_refresh
                ADD CONSTRAINT oauth2_refresh_app_foreign
                FOREIGN KEY (app_id)
                REFERENCES msz_apps (app_id)
                ON UPDATE CASCADE
                ON DELETE CASCADE;
        SQL);

        $snowflake = new \Index\Snowflake\RandomSnowflake;
        $stmt = $conn->prepare('UPDATE msz_apps SET app_id = ? WHERE app_id = ?');
        $result = $conn->query('SELECT app_id, UNIX_TIMESTAMP(app_created) FROM msz_apps');
        while($result->next()) {
            $stmt->addParameter(1, (string)$snowflake->next(at: $result->getInteger(1) * 1000));
            $stmt->addParameter(2, $result->getString(0));
            $stmt->execute();
        }
    }
}