/**
 * POS-002 — Add `source`, `terminal_id`, `cash_session_id` to `orders_orders`;
 * drop NOT NULL on `user_id`; add `COMPLETED` to the state CHECK.
 *
 * The `source` column distinguishes ecommerce / pos / admin sales. POS sales
 * may have `user_id IS NULL` (walk-in customer); ecommerce and admin sales
 * must have a non-null `user_id` (enforced by the application layer; this
 * migration only relaxes the column).
 *
 * The `terminal_id` and `cash_session_id` FKs use `ON DELETE SET NULL` so
 * decommissioning a terminal or closing its session does not delete
 * historical sales.
 *
 * The state CHECK is rewritten with the new `COMPLETED` value. POS sales
 * transition PENDING → AWAITING_PAYMENT → PAID → COMPLETED, skipping
 * SHIPPED / DELIVERED.
 *
 * @param {import('node-pg-migrate').MigrationBuilder} pgm
 */

export const up = (pgm) => {
  // ── Add columns ──────────────────────────────────────────────────────────
  pgm.sql(`
    ALTER TABLE orders_orders
      ADD COLUMN IF NOT EXISTS source text NOT NULL DEFAULT 'ecommerce'
  `);
  pgm.sql(`
    DO $$
    BEGIN
      IF NOT EXISTS (
        SELECT 1 FROM pg_constraint
        WHERE conname = 'orders_orders_source_check'
      ) THEN
        ALTER TABLE orders_orders
          ADD CONSTRAINT orders_orders_source_check
          CHECK (source IN ('ecommerce','pos','admin'));
      END IF;
    END $$
  `);

  pgm.sql(`ALTER TABLE orders_orders ADD COLUMN IF NOT EXISTS terminal_id uuid`);
  pgm.sql(`ALTER TABLE orders_orders ADD COLUMN IF NOT EXISTS cash_session_id uuid`);

  pgm.sql(`
    DO $$
    BEGIN
      IF NOT EXISTS (
        SELECT 1 FROM pg_constraint
        WHERE conname = 'orders_orders_terminal_id_fkey'
      ) THEN
        ALTER TABLE orders_orders
          ADD CONSTRAINT orders_orders_terminal_id_fkey
          FOREIGN KEY (terminal_id) REFERENCES pos_terminals(id) ON DELETE SET NULL;
      END IF;
    END $$
  `);
  pgm.sql(`
    DO $$
    BEGIN
      IF NOT EXISTS (
        SELECT 1 FROM pg_constraint
        WHERE conname = 'orders_orders_cash_session_id_fkey'
      ) THEN
        ALTER TABLE orders_orders
          ADD CONSTRAINT orders_orders_cash_session_id_fkey
          FOREIGN KEY (cash_session_id) REFERENCES pos_cash_sessions(id) ON DELETE SET NULL;
      END IF;
    END $$
  `);

  // ── Indexes ──────────────────────────────────────────────────────────────
  pgm.createIndex('orders_orders', 'source', { name: 'orders_orders_source_idx' });
  pgm.createIndex('orders_orders', 'terminal_id', {
    name: 'orders_orders_terminal_idx',
    where: 'terminal_id IS NOT NULL',
  });
  pgm.createIndex('orders_orders', 'cash_session_id', {
    name: 'orders_orders_cash_session_idx',
    where: 'cash_session_id IS NOT NULL',
  });

  // ── Walk-in customers (POS only) ─────────────────────────────────────────
  pgm.sql(`ALTER TABLE orders_orders ALTER COLUMN user_id DROP NOT NULL`);

  // CHECK: walk-in customers (user_id NULL) are allowed only for POS sales.
  // Ecommerce and admin sales must have a non-null user_id. DB-level invariant
  // enforced in addition to the application-level check.
  pgm.sql(`
    DO $$
    BEGIN
      IF NOT EXISTS (
        SELECT 1 FROM pg_constraint
        WHERE conname = 'orders_orders_user_required_when_not_pos'
      ) THEN
        ALTER TABLE orders_orders
          ADD CONSTRAINT orders_orders_user_required_when_not_pos
          CHECK (source = 'pos' OR user_id IS NOT NULL);
      END IF;
    END $$
  `);

  // ── Add COMPLETED to state CHECK ─────────────────────────────────────────
  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_state_check`);
  pgm.sql(`
    ALTER TABLE orders_orders
      ADD CONSTRAINT orders_orders_state_check
      CHECK (state IN (
        'PENDING',
        'AWAITING_PAYMENT',
        'PAID',
        'PROCESSING',
        'SHIPPED',
        'DELIVERED',
        'COMPLETED',
        'CANCELLED',
        'REFUNDED',
        'PARTIALLY_REFUNDED'
      ))
  `);
};

export const down = (pgm) => {
  // Re-tighten state CHECK to the pre-COMPLETED set; this will fail if any
  // COMPLETED rows exist.
  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_state_check`);
  pgm.sql(`
    ALTER TABLE orders_orders
      ADD CONSTRAINT orders_orders_state_check
      CHECK (state IN (
        'PENDING','AWAITING_PAYMENT','PAID','PROCESSING',
        'SHIPPED','DELIVERED','CANCELLED','REFUNDED','PARTIALLY_REFUNDED'
      ))
  `);

  // user_id becomes NOT NULL again; fails if any NULL rows exist.
  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_user_required_when_not_pos`);
  pgm.sql(`ALTER TABLE orders_orders ALTER COLUMN user_id SET NOT NULL`);

  pgm.sql(`DROP INDEX IF EXISTS orders_orders_cash_session_idx`);
  pgm.sql(`DROP INDEX IF EXISTS orders_orders_terminal_idx`);
  pgm.sql(`DROP INDEX IF EXISTS orders_orders_source_idx`);

  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_cash_session_id_fkey`);
  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_terminal_id_fkey`);
  pgm.sql(`ALTER TABLE orders_orders DROP COLUMN IF EXISTS cash_session_id`);
  pgm.sql(`ALTER TABLE orders_orders DROP COLUMN IF EXISTS terminal_id`);
  pgm.sql(`ALTER TABLE orders_orders DROP CONSTRAINT IF EXISTS orders_orders_source_check`);
  pgm.sql(`ALTER TABLE orders_orders DROP COLUMN IF EXISTS source`);
};
