BEGIN;

CREATE TABLE IF NOT EXISTS strategy_run (
  run_id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  started_at TIMESTAMPTZ,
  stopped_at TIMESTAMPTZ,
  status TEXT NOT NULL,
  strategy TEXT,
  mode TEXT,
  broker TEXT,
  meta JSONB
);

ALTER TABLE strategy_log ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE strategy_log ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE engine_status ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE engine_status ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE engine_event ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE engine_event ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE paper_broker_account ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE paper_broker_account ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE paper_position ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE paper_position ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE paper_order ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE paper_order ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE paper_trade ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE paper_trade ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE paper_equity_curve ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE paper_equity_curve ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE engine_state ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE engine_state ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE engine_state_paper ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE engine_state_paper ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE mtm_ledger ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE mtm_ledger ADD COLUMN IF NOT EXISTS run_id TEXT;

ALTER TABLE event_ledger ADD COLUMN IF NOT EXISTS user_id TEXT;
ALTER TABLE event_ledger ADD COLUMN IF NOT EXISTS run_id TEXT;

-- Temporarily disable user triggers to allow backfill on STOPPED runs.
ALTER TABLE engine_status DISABLE TRIGGER USER;
ALTER TABLE engine_state DISABLE TRIGGER USER;
ALTER TABLE engine_state_paper DISABLE TRIGGER USER;
ALTER TABLE paper_broker_account DISABLE TRIGGER USER;
ALTER TABLE paper_order DISABLE TRIGGER USER;
ALTER TABLE paper_trade DISABLE TRIGGER USER;
ALTER TABLE mtm_ledger DISABLE TRIGGER USER;
ALTER TABLE event_ledger DISABLE TRIGGER USER;
ALTER TABLE paper_position DISABLE TRIGGER USER;
ALTER TABLE paper_equity_curve DISABLE TRIGGER USER;

DO $$
DECLARE
  default_user_id TEXT;
BEGIN
  SELECT id INTO default_user_id FROM app_user ORDER BY username LIMIT 1;
  IF default_user_id IS NULL THEN
    RAISE EXCEPTION 'No app_user rows exist for default_user_id';
  END IF;

  INSERT INTO strategy_run (run_id, user_id, status)
  VALUES ('default_run', default_user_id, 'STOPPED')
  ON CONFLICT (run_id) DO NOTHING;

  UPDATE strategy_log
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE engine_status
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE engine_event
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE paper_broker_account
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE paper_position
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE paper_order
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE paper_trade
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE paper_equity_curve
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE engine_state
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE engine_state_paper
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE mtm_ledger
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;

  UPDATE event_ledger
    SET user_id = default_user_id,
        run_id = 'default_run'
    WHERE user_id IS NULL OR run_id IS NULL;
END $$;

ALTER TABLE strategy_log ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE strategy_log ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE engine_status ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE engine_status ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE engine_event ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE engine_event ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE paper_broker_account ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE paper_broker_account ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE paper_position ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE paper_position ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE paper_order ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE paper_order ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE paper_trade ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE paper_trade ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE paper_equity_curve ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE paper_equity_curve ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE engine_state ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE engine_state ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE engine_state_paper ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE engine_state_paper ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE mtm_ledger ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE mtm_ledger ALTER COLUMN run_id SET NOT NULL;

ALTER TABLE event_ledger ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE event_ledger ALTER COLUMN run_id SET NOT NULL;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_strategy_log_user_id') THEN
    ALTER TABLE strategy_log
      ADD CONSTRAINT fk_strategy_log_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_strategy_log_run_id') THEN
    ALTER TABLE strategy_log
      ADD CONSTRAINT fk_strategy_log_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_status_user_id') THEN
    ALTER TABLE engine_status
      ADD CONSTRAINT fk_engine_status_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_status_run_id') THEN
    ALTER TABLE engine_status
      ADD CONSTRAINT fk_engine_status_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_event_user_id') THEN
    ALTER TABLE engine_event
      ADD CONSTRAINT fk_engine_event_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_event_run_id') THEN
    ALTER TABLE engine_event
      ADD CONSTRAINT fk_engine_event_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_broker_account_user_id') THEN
    ALTER TABLE paper_broker_account
      ADD CONSTRAINT fk_paper_broker_account_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_broker_account_run_id') THEN
    ALTER TABLE paper_broker_account
      ADD CONSTRAINT fk_paper_broker_account_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_position_user_id') THEN
    ALTER TABLE paper_position
      ADD CONSTRAINT fk_paper_position_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_position_run_id') THEN
    ALTER TABLE paper_position
      ADD CONSTRAINT fk_paper_position_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_order_user_id') THEN
    ALTER TABLE paper_order
      ADD CONSTRAINT fk_paper_order_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_order_run_id') THEN
    ALTER TABLE paper_order
      ADD CONSTRAINT fk_paper_order_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_trade_user_id') THEN
    ALTER TABLE paper_trade
      ADD CONSTRAINT fk_paper_trade_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_trade_run_id') THEN
    ALTER TABLE paper_trade
      ADD CONSTRAINT fk_paper_trade_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_equity_curve_user_id') THEN
    ALTER TABLE paper_equity_curve
      ADD CONSTRAINT fk_paper_equity_curve_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paper_equity_curve_run_id') THEN
    ALTER TABLE paper_equity_curve
      ADD CONSTRAINT fk_paper_equity_curve_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_state_user_id') THEN
    ALTER TABLE engine_state
      ADD CONSTRAINT fk_engine_state_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_state_run_id') THEN
    ALTER TABLE engine_state
      ADD CONSTRAINT fk_engine_state_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_state_paper_user_id') THEN
    ALTER TABLE engine_state_paper
      ADD CONSTRAINT fk_engine_state_paper_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_engine_state_paper_run_id') THEN
    ALTER TABLE engine_state_paper
      ADD CONSTRAINT fk_engine_state_paper_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_mtm_ledger_user_id') THEN
    ALTER TABLE mtm_ledger
      ADD CONSTRAINT fk_mtm_ledger_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_mtm_ledger_run_id') THEN
    ALTER TABLE mtm_ledger
      ADD CONSTRAINT fk_mtm_ledger_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_event_ledger_user_id') THEN
    ALTER TABLE event_ledger
      ADD CONSTRAINT fk_event_ledger_user_id FOREIGN KEY (user_id) REFERENCES app_user(id) ON DELETE CASCADE;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_event_ledger_run_id') THEN
    ALTER TABLE event_ledger
      ADD CONSTRAINT fk_event_ledger_run_id FOREIGN KEY (run_id) REFERENCES strategy_run(run_id) ON DELETE CASCADE;
  END IF;
END $$;

CREATE INDEX IF NOT EXISTS idx_strategy_log_user_run ON strategy_log (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_engine_status_user_run ON engine_status (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_engine_event_user_run ON engine_event (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_paper_broker_account_user_run ON paper_broker_account (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_paper_position_user_run ON paper_position (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_paper_order_user_run ON paper_order (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_paper_trade_user_run ON paper_trade (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_paper_equity_curve_user_run ON paper_equity_curve (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_engine_state_user_run ON engine_state (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_engine_state_paper_user_run ON engine_state_paper (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_mtm_ledger_user_run ON mtm_ledger (user_id, run_id);
CREATE INDEX IF NOT EXISTS idx_event_ledger_user_run ON event_ledger (user_id, run_id);

CREATE INDEX IF NOT EXISTS idx_strategy_log_user_run_ts ON strategy_log (user_id, run_id, ts DESC);
CREATE INDEX IF NOT EXISTS idx_engine_event_user_run_ts ON engine_event (user_id, run_id, ts DESC);
CREATE INDEX IF NOT EXISTS idx_paper_order_user_run_ts ON paper_order (user_id, run_id, "timestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_paper_trade_user_run_ts ON paper_trade (user_id, run_id, "timestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_paper_equity_curve_user_run_ts ON paper_equity_curve (user_id, run_id, "timestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_mtm_ledger_user_run_ts ON mtm_ledger (user_id, run_id, "timestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_event_ledger_user_run_ts ON event_ledger (user_id, run_id, "timestamp" DESC);

ALTER TABLE engine_status ENABLE TRIGGER USER;
ALTER TABLE engine_state ENABLE TRIGGER USER;
ALTER TABLE engine_state_paper ENABLE TRIGGER USER;
ALTER TABLE paper_broker_account ENABLE TRIGGER USER;
ALTER TABLE paper_order ENABLE TRIGGER USER;
ALTER TABLE paper_trade ENABLE TRIGGER USER;
ALTER TABLE mtm_ledger ENABLE TRIGGER USER;
ALTER TABLE event_ledger ENABLE TRIGGER USER;
ALTER TABLE paper_position ENABLE TRIGGER USER;
ALTER TABLE paper_equity_curve ENABLE TRIGGER USER;

COMMIT;
