import { DataTypes, type QueryInterface } from 'sequelize';
import { AUDIO_FILE_KINDS } from '@/shared/constants/audio-files';

/**
 * Workstream 13 — generalize `audio_files` into a flexible sound library. A row
 * is now one of three kinds (`file` | `url` | `recipe`):
 * - `file` / `url` populate `url` (uploaded binary or external link);
 * - `recipe` populates the new `recipe` JSONB (client-synthesized sound) and
 *   leaves `url` null — so `url` becomes nullable.
 *
 * `recipe` rows are played purely via the Web Audio API in the browser; they
 * never reference the file subsystem and so are exempt from the download
 * ownership check.
 *
 * This migration is idempotent: columns/enums are only added if missing.
 */
async function columnExists(
  queryInterface: QueryInterface,
  table: string,
  column: string,
): Promise<boolean> {
  const [results] = await queryInterface.sequelize.query(`
    SELECT 1 FROM information_schema.columns
    WHERE table_name = '${table}' AND column_name = '${column}'
  `);
  return (results as unknown[]).length > 0;
}

export default {
  up: async (queryInterface: QueryInterface) => {
    // Create enum type if not exists
    await queryInterface.sequelize.query(`
      DO 'BEGIN
        CREATE TYPE "public"."enum_audio_files_kind" AS ENUM(${AUDIO_FILE_KINDS.map((v) => `''${v}''`).join(', ')});
      EXCEPTION WHEN duplicate_object THEN null; END';
    `);

    if (!(await columnExists(queryInterface, 'audio_files', 'kind'))) {
      await queryInterface.addColumn('audio_files', 'kind', {
        type: DataTypes.ENUM(...AUDIO_FILE_KINDS),
        allowNull: false,
        defaultValue: 'file',
      });
    }

    if (!(await columnExists(queryInterface, 'audio_files', 'recipe'))) {
      await queryInterface.addColumn('audio_files', 'recipe', {
        type: DataTypes.JSONB,
        allowNull: true,
      });
    }

    // Make url nullable (changeColumn is idempotent)
    await queryInterface.changeColumn('audio_files', 'url', {
      type: DataTypes.STRING(2083),
      allowNull: true,
    });
  },

  down: async (queryInterface: QueryInterface) => {
    await queryInterface.changeColumn('audio_files', 'url', {
      type: DataTypes.STRING(2083),
      allowNull: false,
    });
    await queryInterface.removeColumn('audio_files', 'recipe');
    await queryInterface.removeColumn('audio_files', 'kind');
    // Drop the enum type left behind by the ENUM column (Postgres).
    await queryInterface.sequelize.query(
      'DROP TYPE IF EXISTS "enum_audio_files_kind";',
    );
  },
};
