// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
//
// SPDX-License-Identifier: Apache-2.0
'use strict';

/** @type {import('sequelize-cli').Migration} */
import { DataTypes, QueryInterface } from 'sequelize';

export default {
  up: async (queryInterface: QueryInterface) => {
    // Helper to check if a constraint exists (robust for schema/casing)
    const constraintExists = async (
      tableName: string,
      constraintName: string,
    ): Promise<boolean> => {
      const [results] = await queryInterface.sequelize.query(
        `SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = 'public' AND table_name = '${tableName}' AND constraint_name = '${constraintName}';`,
      );
      return results.length > 0;
    };

    // 1. Create EvseTypes table
    await queryInterface.createTable('EvseTypes', {
      databaseId: {
        type: DataTypes.INTEGER,
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
      },
      id: {
        type: DataTypes.INTEGER,
        allowNull: true,
      },
      connectorId: {
        type: DataTypes.INTEGER,
        allowNull: true,
      },
      tenantId: {
        type: DataTypes.INTEGER,
        allowNull: false,
        references: {
          model: 'Tenants',
          key: 'id',
        },
        onUpdate: 'CASCADE',
        onDelete: 'RESTRICT',
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
      },
    });

    // 2. Add all missing columns
    await queryInterface.renameColumn('ChargingNeeds', 'evseDatabaseId', 'evseId');
    await queryInterface.addColumn('Evses', 'stationId', {
      type: DataTypes.STRING(36),
      allowNull: true,
    });
    await queryInterface.addColumn('TransactionEvents', 'idTokenValue', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.removeColumn('Authorizations', 'groupIdTokenId');
    await queryInterface.addColumn('Authorizations', 'tenantPartnerId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'evseId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Tariffs', 'connectorId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'groupAuthorizationId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.removeColumn('LocalListAuthorizations', 'idTokenId');
    await queryInterface.addColumn('LocalListAuthorizations', 'idToken', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.sequelize.query(
      'UPDATE "LocalListAuthorizations" SET "idToken" = \'\' WHERE "idToken" IS NULL;',
    );
    await queryInterface.changeColumn('LocalListAuthorizations', 'idToken', {
      type: DataTypes.STRING,
      allowNull: false,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'idTokenType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'additionalInfo', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'status', {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: 'Accepted',
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'cacheExpiryDateTime', {
      type: DataTypes.DATE,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'chargingPriority', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'language1', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'language2', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'personalMessage', {
      type: DataTypes.JSON,
      allowNull: true,
    });
    await queryInterface.removeColumn('LocalListAuthorizations', 'idTokenInfoId');
    await queryInterface.addColumn('LocalListAuthorizations', 'customData', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'evseTypeId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('TransactionEvents', 'idTokenType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.removeColumn('TransactionEvents', 'idTokenId');
    await queryInterface.addColumn('Evses', 'evseId', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'physicalReference', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'removed', {
      type: DataTypes.BOOLEAN,
      allowNull: true,
    });
    await queryInterface.addColumn('StopTransactions', 'idTokenValue', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('StopTransactions', 'idTokenType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.removeColumn('StopTransactions', 'idTokenDatabaseId');
    // ChargingStation: Add missing columns
    await queryInterface.addColumn('ChargingStations', 'coordinates', {
      type: DataTypes.GEOMETRY('POINT'),
      allowNull: true,
    });
    await queryInterface.addColumn('ChargingStations', 'floorLevel', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('ChargingStations', 'parkingRestrictions', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('ChargingStations', 'capabilities', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('Locations', 'publishUpstream', {
      type: DataTypes.BOOLEAN,
      defaultValue: true,
    });
    await queryInterface.addColumn('Locations', 'timeZone', {
      type: DataTypes.STRING,
      defaultValue: 'UTC',
    });
    await queryInterface.addColumn('Locations', 'parkingType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Locations', 'facilities', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('Locations', 'openingHours', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    // Tariff: Add missing column
    await queryInterface.addColumn('Tariffs', 'tariffAltText', {
      type: DataTypes.STRING,
      allowNull: true,
    });

    await queryInterface.addColumn('MeterValues', 'customData', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('MeterValues', 'tariffId', {
      type: DataTypes.INTEGER,
      allowNull: true,
      references: {
        model: 'Tariffs',
        key: 'id',
      },
      onUpdate: 'CASCADE',
      onDelete: 'SET NULL',
    });
    await queryInterface.addColumn('MeterValues', 'transactionId', {
      type: DataTypes.STRING,
      allowNull: true,
    });

    await queryInterface.removeColumn('Transactions', 'evseDatabaseId');
    await queryInterface.addColumn('Transactions', 'locationId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'evseId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'connectorId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'authorizationId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'tariffId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'startTime', {
      type: DataTypes.DATE,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'endTime', {
      type: DataTypes.DATE,
      allowNull: true,
    });
    await queryInterface.addColumn('Transactions', 'customData', {
      type: DataTypes.JSONB,
      allowNull: true,
    });

    // 3. Drop dependent foreign key constraints
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_evseDatabaseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "ChargingNeeds" DROP CONSTRAINT IF EXISTS "ChargingNeeds_evseDatabaseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Components" DROP CONSTRAINT IF EXISTS "Components_evseDatabaseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "TransactionEvents" DROP CONSTRAINT IF EXISTS "TransactionEvents_evseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Reservations" DROP CONSTRAINT IF EXISTS "Reservations_evseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "VariableAttributes" DROP CONSTRAINT IF EXISTS "VariableAttributes_evseDatabaseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Components" DROP CONSTRAINT IF EXISTS "Components_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Reservations" DROP CONSTRAINT IF EXISTS "Reservations_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "TransactionEvents" DROP CONSTRAINT IF EXISTS "TransactionEvents_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "VariableAttributes" DROP CONSTRAINT IF EXISTS "VariableAttributes_evseTypeId_fkey";',
    );

    // 4. Fix the Evses table
    await queryInterface.sequelize.query(
      'ALTER TABLE "Evses" DROP CONSTRAINT IF EXISTS "Evses_pkey";',
    );

    // Populate EvseTypes from existing data before adding foreign keys
    await queryInterface.sequelize.query(`
      INSERT INTO "EvseTypes" ("id", "tenantId", "connectorId", "createdAt", "updatedAt")
      SELECT "id", "tenantId", "connectorId", NOW(), NOW()
      FROM "Evses";
    `);

    // Truncate Evses table after migration
    await queryInterface.sequelize.query('TRUNCATE TABLE "Evses" CASCADE;');

    await queryInterface.removeColumn('Evses', 'databaseId');
    await queryInterface.removeColumn('Evses', 'connectorId');
    await queryInterface.removeColumn('Evses', 'id');
    // Sequelize does not support adding a primary key via addColumn, so we do it in two steps
    await queryInterface.addColumn('Evses', 'id', {
      type: DataTypes.INTEGER,
      autoIncrement: true,
    });
    await queryInterface.sequelize.query(
      'ALTER TABLE "Evses" ADD CONSTRAINT "Evses_pkey" PRIMARY KEY (id);',
    );

    await queryInterface.addColumn('Connectors', 'evseTypeConnectorId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'type', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'format', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'powerType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'maximumAmperage', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'maximumVoltage', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'maximumPowerWatts', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Connectors', 'termsAndConditionsUrl', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    // Foreign key constraints for relationships (add only if not exists, drop if exists first)
    if (await constraintExists('Connectors', 'Connectors_evseId_fkey')) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "Connectors" DROP CONSTRAINT IF EXISTS "Connectors_evseId_fkey";',
      );
    }
    if (!(await constraintExists('Connectors', 'Connectors_evseId_fkey'))) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "Connectors" ADD CONSTRAINT "Connectors_evseId_fkey" FOREIGN KEY ("evseId") REFERENCES "Evses" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
      );
    }
    if (!(await constraintExists('Connectors', 'Connectors_stationId_fkey'))) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "Connectors" ADD CONSTRAINT "Connectors_stationId_fkey" FOREIGN KEY ("stationId") REFERENCES "ChargingStations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
      );
    }
    if (!(await constraintExists('ChargingStations', 'ChargingStations_locationId_fkey'))) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "ChargingStations" ADD CONSTRAINT "ChargingStations_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Locations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
      );
    }
    if (!(await constraintExists('Authorizations', 'Authorizations_groupAuthorizationId_fkey'))) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "Authorizations" ADD CONSTRAINT "Authorizations_groupAuthorizationId_fkey" FOREIGN KEY ("groupAuthorizationId") REFERENCES "Authorizations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
      );
    }
    if (!(await constraintExists('ChargingNeeds', 'ChargingNeeds_transactionDatabaseId_fkey'))) {
      await queryInterface.sequelize.query(
        'ALTER TABLE "ChargingNeeds" ADD CONSTRAINT "ChargingNeeds_transactionDatabaseId_fkey" FOREIGN KEY ("transactionDatabaseId") REFERENCES "Transactions" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
      );
    }

    //  Rename partnerProfile to partnerProfileOCPI in TenantPartners ---
    const tenantPartnersTable = 'TenantPartners';
    const oldColumn = 'partnerProfile';
    const newColumn = 'partnerProfileOCPI';
    const tenantPartnersDesc = await queryInterface.describeTable(tenantPartnersTable);
    if (tenantPartnersDesc[oldColumn] && !tenantPartnersDesc[newColumn]) {
      await queryInterface.renameColumn(tenantPartnersTable, oldColumn, newColumn);
    }

    // 5. Re-create all foreign key constraints
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_evseId_fkey" FOREIGN KEY ("evseId") REFERENCES "Evses" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "ChargingNeeds" ADD CONSTRAINT "ChargingNeeds_evseId_fkey" FOREIGN KEY ("evseId") REFERENCES "Evses" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Authorizations" ADD CONSTRAINT "Authorizations_tenantPartnerId_fkey" FOREIGN KEY ("tenantPartnerId") REFERENCES "TenantPartners" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Evses" ADD CONSTRAINT "Evses_stationId_fkey" FOREIGN KEY ("stationId") REFERENCES "ChargingStations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Tariffs" ADD CONSTRAINT "Tariffs_connectorId_fkey" FOREIGN KEY ("connectorId") REFERENCES "Connectors" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_tariffId_fkey" FOREIGN KEY ("tariffId") REFERENCES "Tariffs" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_authorizationId_fkey" FOREIGN KEY ("authorizationId") REFERENCES "Authorizations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_connectorId_fkey" FOREIGN KEY ("connectorId") REFERENCES "Connectors" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Locations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "LocalListAuthorizations" ADD CONSTRAINT "LocalListAuthorizations_groupAuthorizationId_fkey" FOREIGN KEY ("groupAuthorizationId") REFERENCES "Authorizations" (id) ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Components" ADD CONSTRAINT "Components_evseTypeId_fkey" FOREIGN KEY ("evseDatabaseId") REFERENCES "EvseTypes" ("databaseId") ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Reservations" ADD CONSTRAINT "Reservations_evseTypeId_fkey" FOREIGN KEY ("evseId") REFERENCES "EvseTypes" ("databaseId") ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "TransactionEvents" ADD CONSTRAINT "TransactionEvents_evseTypeId_fkey" FOREIGN KEY ("evseId") REFERENCES "EvseTypes" ("databaseId") ON UPDATE CASCADE ON DELETE SET NULL;',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "VariableAttributes" ADD CONSTRAINT "VariableAttributes_evseTypeId_fkey" FOREIGN KEY ("evseDatabaseId") REFERENCES "EvseTypes" ("databaseId") ON UPDATE CASCADE ON DELETE SET NULL;',
    );
  },

  down: async (queryInterface: QueryInterface) => {
    // 1. Drop all foreign key constraints added in up
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_evseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_tariffId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_authorizationId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_connectorId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_locationId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "ChargingNeeds" DROP CONSTRAINT IF EXISTS "ChargingNeeds_evseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Authorizations" DROP CONSTRAINT IF EXISTS "Authorizations_tenantPartnerId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Authorizations" DROP CONSTRAINT IF EXISTS "Authorizations_groupAuthorizationId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Evses" DROP CONSTRAINT IF EXISTS "Evses_stationId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Connectors" DROP CONSTRAINT IF EXISTS "Connectors_evseId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Tariffs" DROP CONSTRAINT IF EXISTS "Tariffs_connectorId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "LocalListAuthorizations" DROP CONSTRAINT IF EXISTS "LocalListAuthorizations_groupAuthorizationId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Components" DROP CONSTRAINT IF EXISTS "Components_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "Reservations" DROP CONSTRAINT IF EXISTS "Reservations_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "TransactionEvents" DROP CONSTRAINT IF EXISTS "TransactionEvents_evseTypeId_fkey";',
    );
    await queryInterface.sequelize.query(
      'ALTER TABLE "VariableAttributes" DROP CONSTRAINT IF EXISTS "VariableAttributes_evseTypeId_fkey";',
    );

    // 2. Remove all columns added in up
    await queryInterface.renameColumn('ChargingNeeds', 'evseId', 'evseDatabaseId');
    await queryInterface.removeColumn('Evses', 'stationId');
    await queryInterface.removeColumn('TransactionEvents', 'idTokenValue');
    await queryInterface.removeColumn('Transactions', 'evseId');
    await queryInterface.removeColumn('Authorizations', 'tenantPartnerId');
    await queryInterface.removeColumn('Connectors', 'evseId');
    await queryInterface.removeColumn('Tariffs', 'connectorId');
    await queryInterface.removeColumn('Transactions', 'tariffId');
    await queryInterface.removeColumn('Transactions', 'authorizationId');
    await queryInterface.removeColumn('Transactions', 'connectorId');
    await queryInterface.removeColumn('Transactions', 'locationId');
    await queryInterface.removeColumn('LocalListAuthorizations', 'groupAuthorizationId');
    await queryInterface.addColumn('LocalListAuthorizations', 'idTokenId', {
      type: DataTypes.INTEGER,
      allowNull: true,
      references: {
        model: 'IdTokens',
        key: 'id',
      },
      onUpdate: 'CASCADE',
      onDelete: 'SET NULL',
    });
    await queryInterface.removeColumn('LocalListAuthorizations', 'idToken');
    await queryInterface.addColumn('LocalListAuthorizations', 'idTokenType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'additionalInfo', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'status', {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: 'Accepted',
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'cacheExpiryDateTime', {
      type: DataTypes.DATE,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'chargingPriority', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'language1', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'language2', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('LocalListAuthorizations', 'personalMessage', {
      type: DataTypes.JSON,
      allowNull: true,
    });
    await queryInterface.removeColumn('LocalListAuthorizations', 'idTokenInfoId');
    await queryInterface.addColumn('LocalListAuthorizations', 'customData', {
      type: DataTypes.JSONB,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'evseTypeId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('TransactionEvents', 'idTokenType', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.removeColumn('TransactionEvents', 'idTokenId');
    await queryInterface.addColumn('Evses', 'evseId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'physicalReference', {
      type: DataTypes.STRING,
      allowNull: true,
    });
    await queryInterface.addColumn('Evses', 'removed', {
      type: DataTypes.BOOLEAN,
      allowNull: true,
    });
    // ChargingStation: Remove columns
    await queryInterface.removeColumn('ChargingStations', 'coordinates');
    await queryInterface.removeColumn('ChargingStations', 'floorLevel');
    await queryInterface.removeColumn('ChargingStations', 'parkingRestrictions');
    await queryInterface.removeColumn('ChargingStations', 'capabilities');
    // Tariff: Remove column
    await queryInterface.removeColumn('Tariffs', 'tariffAltText');

    // 3. Drop EvseTypes table
    await queryInterface.dropTable('EvseTypes');

    // 4. Restore Evses table PK/index as needed
    await queryInterface.addColumn('Evses', 'databaseId', {
      type: DataTypes.INTEGER,
      allowNull: true,
    });
    await queryInterface.sequelize.query(
      'ALTER TABLE "Evses" DROP CONSTRAINT IF EXISTS "Evses_pkey";',
    );

    // Revert partnerProfileOCPI to partnerProfile in TenantPartners ---
    const tenantPartnersTable = 'TenantPartners';
    const oldColumn = 'partnerProfile';
    const newColumn = 'partnerProfileOCPI';
    const tenantPartnersDesc = await queryInterface.describeTable(tenantPartnersTable);
    if (tenantPartnersDesc[newColumn] && !tenantPartnersDesc[oldColumn]) {
      await queryInterface.renameColumn(tenantPartnersTable, newColumn, oldColumn);
    }
  },
};
