import type { QueryInterface } from 'sequelize';
import type { Migration } from '../migrate';

const indexExists = async (table: string, indexName: string, queryInterface: QueryInterface) => {
  const indexes = await queryInterface.showIndex(table);
  return indexes && Array.isArray(indexes) && indexes.some((index: { name: string }) => index.name === indexName);
};

const createIndexIfNotExists = async (
  queryInterface: QueryInterface,
  table: string,
  indexName: string,
  rawSQL: string
) => {
  if (await indexExists(table, indexName, queryInterface)) {
    /* eslint-disable no-console */
    console.log(`Index ${indexName} already exists on ${table}, skipping...`);
    return;
  }
  await queryInterface.sequelize.query(rawSQL);
};

export const up: Migration = async ({ context: queryInterface }) => {
  try {
    await createIndexIfNotExists(
      queryInterface,
      'credit_grants',
      'idx_credit_grant_stats_by_grantor',
      "CREATE INDEX idx_credit_grant_stats_by_grantor ON credit_grants(json_extract(metadata, '$.granted_by'), currency_id, created_at) WHERE json_extract(metadata, '$.granted_by') IS NOT NULL"
    );

    console.log(
      'Successfully created partial index on metadata.granted_by, currency_id, created_at (WHERE granted_by IS NOT NULL)'
    );
  } catch (error) {
    console.error('Failed to create granted_by index', error);
    throw error;
  }
};

export const down: Migration = async ({ context: queryInterface }) => {
  try {
    const indexName = 'idx_credit_grant_stats_by_grantor';
    if (await indexExists('credit_grants', indexName, queryInterface)) {
      await queryInterface.removeIndex('credit_grants', indexName);
      console.log(`Successfully removed index ${indexName}`);
    }
  } catch (error) {
    console.error('Failed to remove granted_by index', error);
    throw error;
  }
};
