/**
 * Reconcile user profile schema (B5 of reconcile-historical-add-scripts).
 *
 * Captures the union of DDL effects from two historical scripts that ran
 * against every long-lived env but were never folded into the migration
 * history:
 *
 *   - `scripts/add-user-profile-columns.js` (script #8) — adds `first_name`,
 *     `last_name`, `username UNIQUE`, `profile_image_url`.
 *   - `scripts/add-user-profile-fields.js`  (script #9) — adds the same first
 *     three plus `bio`, `avatar_url`, 10 preference / notification / display
 *     columns, two new tables (`user_settings`, `user_avatars`), 6 CHECK
 *     constraints, and 6 indexes.
 *
 * Per the convoy's Finding 2, BOTH `profile_image_url` (from #8) AND
 * `avatar_url` (from #9) coexist in prod and are read by runtime code
 * (`pages/api/auth/register.js` reads `profile_image_url`; the user/avatar
 * surface reads `avatar_url`). The redundancy is documented as a separate
 * follow-up convoy `unify-user-avatar-column`; this migration must NOT pick
 * one and drop the other.
 *
 * Idempotency (D2):
 *   - Every column ADD uses `ADD COLUMN IF NOT EXISTS`.
 *   - Both new tables use `CREATE TABLE IF NOT EXISTS`.
 *   - Every index uses `CREATE INDEX IF NOT EXISTS`.
 *   - CHECK constraints are wrapped in `DO $$ ... EXCEPTION WHEN
 *     duplicate_object THEN NULL; END $$;` blocks because Postgres pre-15
 *     does not accept `ADD CONSTRAINT ... IF NOT EXISTS` for CHECK
 *     constraints (matches the historical script's try/catch pattern, R5).
 *
 * Defaults-backfill DML (the `UPDATE users SET ... WHERE ... IS NULL` block
 * at the end of script #9) is intentionally NOT replicated. The column
 * DEFAULT clauses are sufficient on a fresh env (every new row gets the
 * default at insert time) and prod-existing rows already have the values
 * from the historical script's run.
 *
 * Down-migration is a hard stub. This is a reconciliation migration; rolling
 * it back on prod would drop columns that runtime code reads.
 *
 * @type {import('node-pg-migrate').ColumnDefinitions | undefined}
 */
export const shorthands = undefined;

/**
 * @param {import('node-pg-migrate').MigrationBuilder} pgm
 * @returns {void}
 */
export const up = (pgm) => {
  pgm.sql(`
    ALTER TABLE users
      ADD COLUMN IF NOT EXISTS first_name VARCHAR(255),
      ADD COLUMN IF NOT EXISTS last_name VARCHAR(255),
      ADD COLUMN IF NOT EXISTS username VARCHAR(255) UNIQUE,
      ADD COLUMN IF NOT EXISTS profile_image_url TEXT,
      ADD COLUMN IF NOT EXISTS bio TEXT,
      ADD COLUMN IF NOT EXISTS avatar_url TEXT,
      ADD COLUMN IF NOT EXISTS favorite_games JSONB DEFAULT '["MTG"]',
      ADD COLUMN IF NOT EXISTS collection_visibility VARCHAR(20) DEFAULT 'private',
      ADD COLUMN IF NOT EXISTS preferred_currency VARCHAR(3) DEFAULT 'USD',
      ADD COLUMN IF NOT EXISTS cards_per_page INTEGER DEFAULT 50,
      ADD COLUMN IF NOT EXISTS default_view VARCHAR(10) DEFAULT 'grid',
      ADD COLUMN IF NOT EXISTS notifications_email BOOLEAN DEFAULT true,
      ADD COLUMN IF NOT EXISTS notifications_marketing BOOLEAN DEFAULT false,
      ADD COLUMN IF NOT EXISTS two_factor_enabled BOOLEAN DEFAULT false,
      ADD COLUMN IF NOT EXISTS theme VARCHAR(10) DEFAULT 'system',
      ADD COLUMN IF NOT EXISTS language VARCHAR(5) DEFAULT 'en';
  `);

  pgm.sql(`
    CREATE TABLE IF NOT EXISTS user_settings (
      id SERIAL PRIMARY KEY,
      user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
      setting_key VARCHAR(100) NOT NULL,
      setting_value JSONB NOT NULL,
      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      UNIQUE(user_id, setting_key)
    );
  `);

  pgm.sql(`
    CREATE TABLE IF NOT EXISTS user_avatars (
      id SERIAL PRIMARY KEY,
      user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
      filename VARCHAR(255) NOT NULL,
      original_name VARCHAR(255),
      mime_type VARCHAR(100),
      file_size INTEGER,
      file_path TEXT NOT NULL,
      is_active BOOLEAN DEFAULT true,
      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
  `);

  pgm.sql(`
    CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
    CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
    CREATE INDEX IF NOT EXISTS idx_user_settings_user_id ON user_settings(user_id);
    CREATE INDEX IF NOT EXISTS idx_user_settings_key ON user_settings(setting_key);
    CREATE INDEX IF NOT EXISTS idx_user_avatars_user_id ON user_avatars(user_id);
    CREATE INDEX IF NOT EXISTS idx_user_avatars_active ON user_avatars(user_id, is_active);
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_collection_visibility
        CHECK (collection_visibility IN ('private', 'public', 'unlisted'));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_preferred_currency
        CHECK (preferred_currency IN ('USD', 'EUR', 'GBP', 'CAD', 'JPY'));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_cards_per_page
        CHECK (cards_per_page IN (25, 50, 100));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_default_view
        CHECK (default_view IN ('grid', 'list'));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_theme
        CHECK (theme IN ('light', 'dark', 'system'));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);

  pgm.sql(`
    DO $$
    BEGIN
      ALTER TABLE users
        ADD CONSTRAINT check_language
        CHECK (language IN ('en', 'es', 'fr', 'de', 'ja'));
    EXCEPTION
      WHEN duplicate_object THEN NULL;
    END$$;
  `);
};

/**
 * Down-migration is a hard stub. Rolling back this reconciliation would drop
 * columns that runtime code reads (e.g. `pages/api/auth/register.js` writes
 * and reads `profile_image_url`; `pages/api/user/settings.js` reads
 * `theme` / `language` / etc.) and would also drop the `user_settings` and
 * `user_avatars` tables along with any rows in them. If you need to roll
 * forward instead, write a NEW dated migration with a real `down`.
 *
 * @returns {void}
 */
export const down = () => {
  throw new Error(
    '[migration:1781000000005_reconcile-user-profile] Refusing to roll back. ' +
      'This is a reconciliation migration that captures DDL already in prod via ' +
      'scripts/add-user-profile-columns.js and scripts/add-user-profile-fields.js; ' +
      'rolling it back would drop columns that runtime code reads (profile_image_url, ' +
      'avatar_url, theme, language, etc.) and the user_settings / user_avatars tables. ' +
      'Write a new dated migration if a real schema correction is needed.'
  );
};
