import { DataTypes, type QueryInterface } from 'sequelize';
import { POLICY_DOCUMENT_CATEGORY_VALUES } from '@/shared/constants/policy-documents';

/**
 * Workstream 11 — policy/safety acknowledgment persistence.
 *
 * `policy_documents`: tenant/campus-scoped documents (safety protocols + handbook
 * policies) that director/office_manager manage. `version` bumps on change so a
 * new version requires re-acknowledgment.
 *
 * `policy_acknowledgments`: one row per (user, document, version) — a campus
 * staff member's acknowledgment of a specific document version. Unique on
 * (userId, policyDocumentId, version). Plain UUID references (no DB-level FK),
 * matching the rest of the schema (associations use `constraints: false`).
 *
 * This migration is idempotent: tables/enums/indexes are only created if missing.
 */
async function tableExists(
  queryInterface: QueryInterface,
  table: string,
): Promise<boolean> {
  const [results] = await queryInterface.sequelize.query(`
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = 'public' AND table_name = '${table}'
  `);
  return (results as unknown[]).length > 0;
}

async function indexExists(
  queryInterface: QueryInterface,
  indexName: string,
): Promise<boolean> {
  const [results] = await queryInterface.sequelize.query(`
    SELECT 1 FROM pg_indexes WHERE indexname = '${indexName}'
  `);
  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_policy_documents_category" AS ENUM(${POLICY_DOCUMENT_CATEGORY_VALUES.map((v) => `''${v}''`).join(', ')});
      EXCEPTION WHEN duplicate_object THEN null; END';
    `);

    if (!(await tableExists(queryInterface, 'policy_documents'))) {
      await queryInterface.createTable('policy_documents', {
        id: {
          type: DataTypes.UUID,
          defaultValue: DataTypes.UUIDV4,
          primaryKey: true,
        },
        title: { type: DataTypes.TEXT, allowNull: false },
        body: { type: DataTypes.TEXT, allowNull: true },
        category: {
          type: DataTypes.ENUM(...POLICY_DOCUMENT_CATEGORY_VALUES),
          allowNull: false,
        },
        tag: { type: DataTypes.STRING(255), allowNull: true },
        author: { type: DataTypes.STRING(255), allowNull: true },
        steps: { type: DataTypes.JSONB, allowNull: true },
        autism_considerations: { type: DataTypes.JSONB, allowNull: true },
        version: { type: DataTypes.INTEGER, allowNull: false, defaultValue: 1 },
        active: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
        importHash: { type: DataTypes.STRING(255), allowNull: true, unique: true },
        organizationId: { type: DataTypes.UUID, allowNull: true },
        campusId: { type: DataTypes.UUID, allowNull: true },
        createdById: { type: DataTypes.UUID, allowNull: true },
        updatedById: { type: DataTypes.UUID, allowNull: true },
        createdAt: { type: DataTypes.DATE },
        updatedAt: { type: DataTypes.DATE },
        deletedAt: { type: DataTypes.DATE },
      });
    }

    if (!(await tableExists(queryInterface, 'policy_acknowledgments'))) {
      await queryInterface.createTable('policy_acknowledgments', {
        id: {
          type: DataTypes.UUID,
          defaultValue: DataTypes.UUIDV4,
          primaryKey: true,
        },
        policyDocumentId: { type: DataTypes.UUID, allowNull: false },
        version: { type: DataTypes.INTEGER, allowNull: false },
        userId: { type: DataTypes.UUID, allowNull: false },
        acknowledgedAt: { type: DataTypes.DATE, allowNull: false },
        organizationId: { type: DataTypes.UUID, allowNull: true },
        campusId: { type: DataTypes.UUID, allowNull: true },
        createdById: { type: DataTypes.UUID, allowNull: true },
        updatedById: { type: DataTypes.UUID, allowNull: true },
        createdAt: { type: DataTypes.DATE },
        updatedAt: { type: DataTypes.DATE },
      });
    }

    if (!(await indexExists(queryInterface, 'policy_acknowledgments_user_document_version_unique'))) {
      await queryInterface.addIndex('policy_acknowledgments', {
        fields: ['userId', 'policyDocumentId', 'version'],
        unique: true,
        name: 'policy_acknowledgments_user_document_version_unique',
      });
    }
  },

  down: async (queryInterface: QueryInterface) => {
    await queryInterface.dropTable('policy_acknowledgments');
    await queryInterface.dropTable('policy_documents');
    await queryInterface.sequelize.query(
      'DROP TYPE IF EXISTS "enum_policy_documents_category";',
    );
  },
};
