-- wallet resource outbox transaction_id repair and controlled retry.
--
-- This file is deliberately outside initdb/migrations: Phase A must not replay any
-- historical message. Run it only after Phase B (`wallet_event_tag_mode=event_type`)
-- is live, all wallet consumer subscriptions are healthy, and the target rows below
-- have been reviewed. One execution handles at most 100 unlocked rows; repeat while
-- observing MQ lag and consumer errors.
--
-- Preview-only (default, never mutates rows):
--   mysql ... < 20260711_retry_incomplete_resource_outbox.sql
--
-- Explicit Phase-B execution in the same mysql session:
--   SET @execute_wallet_resource_outbox_retry = 1;
--   SOURCE /absolute/path/20260711_retry_incomplete_resource_outbox.sql;

SET @execute_wallet_resource_outbox_retry :=
  IF(COALESCE(@execute_wallet_resource_outbox_retry, 0) = 1, 1, 0);

DROP TEMPORARY TABLE IF EXISTS tmp_wallet_resource_outbox_retry;
CREATE TEMPORARY TABLE tmp_wallet_resource_outbox_retry (
  app_code VARCHAR(32) NOT NULL,
  event_id VARCHAR(128) NOT NULL,
  PRIMARY KEY (app_code, event_id)
) ENGINE=MEMORY;

-- The event list is the complete set currently created through resourceOutboxEvent.
-- Empty transaction_id plus the exact encoder error prevents this maintenance action
-- from touching financial facts or resource failures caused by any other condition.
INSERT INTO tmp_wallet_resource_outbox_retry (app_code, event_id)
SELECT app_code, event_id
FROM wallet_outbox
WHERE asset_type = 'RESOURCE'
  AND event_type IN (
    'GiftConfigChanged',
    'ResourceChanged',
    'ResourceGrantRevoked',
    'ResourceGranted',
    'ResourceGroupChanged',
    'ResourceGroupGranted',
    'UserResourceChanged',
    'VipEffectiveChanged',
    'VipTrialCardGranted'
  )
  AND transaction_id = ''
  AND BINARY last_error = BINARY 'wallet outbox message is incomplete'
  AND status IN ('failed', 'retryable')
  AND worker_id = ''
  AND lock_until_ms IS NULL
ORDER BY created_at_ms, event_id
LIMIT 100;

SELECT
  wo.app_code,
  wo.event_id,
  wo.event_type,
  wo.status,
  wo.retry_count,
  wo.created_at_ms
FROM wallet_outbox wo
JOIN tmp_wallet_resource_outbox_retry target
  ON target.app_code = wo.app_code AND target.event_id = wo.event_id
ORDER BY wo.created_at_ms, wo.event_id;

START TRANSACTION;

-- @execute_wallet_resource_outbox_retry defaults to 0. When explicitly set to 1,
-- transaction_id=event_id restores a stable correlation ID and status=pending asks
-- the already-running Phase-B worker to publish exactly the original outbox fact.
UPDATE wallet_outbox wo
JOIN tmp_wallet_resource_outbox_retry target
  ON target.app_code = wo.app_code AND target.event_id = wo.event_id
SET wo.transaction_id = wo.event_id,
    wo.status = 'pending',
    wo.worker_id = '',
    wo.lock_until_ms = NULL,
    wo.retry_count = 0,
    wo.next_retry_at_ms = NULL,
    wo.last_error = NULL,
    wo.updated_at_ms = CAST(UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000 AS UNSIGNED)
WHERE @execute_wallet_resource_outbox_retry = 1
  AND wo.asset_type = 'RESOURCE'
  AND wo.event_type IN (
    'GiftConfigChanged',
    'ResourceChanged',
    'ResourceGrantRevoked',
    'ResourceGranted',
    'ResourceGroupChanged',
    'ResourceGroupGranted',
    'UserResourceChanged',
    'VipEffectiveChanged',
    'VipTrialCardGranted'
  )
  AND wo.transaction_id = ''
  AND BINARY wo.last_error = BINARY 'wallet outbox message is incomplete'
  AND wo.status IN ('failed', 'retryable')
  AND wo.worker_id = ''
  AND wo.lock_until_ms IS NULL;

SET @wallet_resource_outbox_requeued_rows := ROW_COUNT();
COMMIT;

SELECT
  @execute_wallet_resource_outbox_retry AS execution_enabled,
  @wallet_resource_outbox_requeued_rows AS requeued_rows,
  CASE
    WHEN @execute_wallet_resource_outbox_retry = 1 THEN 'phase_b_batch_requeued'
    ELSE 'preview_only_no_rows_changed'
  END AS result;

DROP TEMPORARY TABLE IF EXISTS tmp_wallet_resource_outbox_retry;
