-- ================================================
-- PT_ENTRAINMENT Workflow Refresh
-- 2026-08-10
-- ALREADY EXECUTED as workflow_version '2.0.0'. The PAYMENT/TRAVEL fixes below (rejected-status
-- guard + scenario-aware PAYMENT success screen) were added to this file AFTER that run, so the
-- live DB does not yet reflect them — see
-- database/entrainment-migrations-v2(2026-08-10)/02aworkflow-refresh-rejected-guard-update.sql,
-- which patches the already-inserted WF_ENTRAINMENT_V8 row and bumps workflow_version to '2.0.1'.
-- This file itself is kept in sync as the source of truth for provisioning a fresh environment
-- from scratch (its workflow_version literal is bumped to '2.0.1' to match).
-- No schema changes. Seed data only.
-- ================================================
--
-- WHY: PT_ENTRAINMENT (program_type_v1.id = 8, key = 'PT_ENTRAINMENT') currently has TWO
-- non-deleted workflow_configuration rows:
--   1. WF_ENTRAINMENT_V5   (generic type-level, 3.0.0, 3 stages: REGISTRATION/PAYMENT/TRAVEL)
--      — database/workflow-config-entrainment-insert.sql
--   2. WF_ENTRAINMENT_EN26_V6 (program-instance-specific for the EN26/April-2026 run, 1.0.0,
--      4 stages: REGISTRATION/PAYMENT/TRAVEL/GOODIES) — the one every live PT_ENTRAINMENT
--      program_v1 row is actually pointed at today (see the trailing UPDATE program_v1 in
--      database/workflow-config-entrainment-en26-insert.sql).
--
-- This migration supersedes BOTH: it soft-deletes every currently-live workflow_configuration
-- (+ workflow_stage + workflow_configuration_variable children) scoped to program_type_key =
-- 'PT_ENTRAINMENT', then inserts one brand-new workflow_configuration reproducing
-- WF_ENTRAINMENT_EN26_V6's structure from scratch — but with only 3 stages
-- (REGISTRATION/PAYMENT/TRAVEL), not 4. Confirmed: goodies and travel are merged (see
-- database/entrainment-migrations-v2(2026-08-10)/03template-refresh.sql STEP 6 — goodies
-- questions are injected directly into FS_TRAVELPLAN, there is no separate FS_GOODIES section),
-- so EN26 V6's 4th "GOODIES" stage (which pointed its permissions at that nonexistent
-- "FS_GOODIES" section and could therefore never actually apply to anything) is dropped rather
-- than reproduced; the goodies fields are submitted together with travel details under Stage
-- 3's existing FS_TRAVELPLAN permissions/SAVE_TRAVEL action. Re-links the same workflow
-- variables EXCEPT 'GOODIES_STATUS' / 'PROGRAM_HAS_GOODIES', dropped along with the stage they
-- existed to serve — nothing in this workflow tracks goodies as a distinct stage/status
-- anymore, so linking them here would be a dangling trace of the removed design. Repoints every
-- program_v1 row that was on one of the old configs onto the new one (workflow_id is a NOT NULL
-- FK on program_v1 — a soft-deleted config must never be left referenced).
--
-- FIXES applied on top of WF_ENTRAINMENT_EN26_V6 (not a verbatim reproduction for PAYMENT —
-- see below), ported over from the equivalent TAT TA26 fixes
-- (database/workflow-config-tat-ta26-payment-final-update.sql):
--   a. PAYMENT stage gating (prerequisite, FS_PAYMENTINVOICE create/update, MAKE_PAYMENT) now
--      also requires {registrationStatus NOT_IN ['rejected']}. EN26_V6 never had this guard, so
--      a registration an admin rejects/denies (e.g. via the generic "deny waitlisted seeker"
--      action, which sets registrationStatus='rejected' — see
--      registration.service.ts updateRegistrationStatus) is NOT 'waitlisted' and could still
--      pass the NOT_IN(['waitlisted']) OR reservedLink check and reach payment.
--   b. MAKE_PAYMENT's onSuccess now uses a scenario-aware successScreenConfig (online success /
--      offline cheque "subject to realization" / offline other / payment-edit-requested, plus a
--      default) instead of one flat successScreen shown for every outcome. FREE_SEAT_REGISTRATION
--      is not included as a scenario here: this stage's own gate requires isFreeSeat=false, so
--      free-seat registrations never reach MAKE_PAYMENT in the first place.
--   c. TRAVEL stage gating (prerequisite, FS_TRAVELPLAN create, SAVE_TRAVEL) now also requires
--      {registrationStatus NOT_IN ['rejected']}, for the same reason as (a): a registration
--      rejected/denied AFTER already completing payment (updateRegistrationStatus does not
--      restrict newStatus by the registration's current status) is not 'waitlisted' and could
--      otherwise still submit travel details.
--
-- OPEN FLAGS — please double-check before running:
--   1. New workflow_key is set to 'WF_ENTRAINMENT_V8' and workflow_name drops the "EN26" season
--      qualifier (this refresh is written as the new generic/current PT_ENTRAINMENT workflow,
--      not scoped to one season) — rename if a specific season key (e.g. EN27) is intended.
--   2. workflow_version is set to '2.0.1' (bumped past the originally-run '2.0.0', which lacked
--      the FIXES above) — adjust if you track versions differently.
--   3. PAYMENT and TRAVEL stage content is NOT verbatim from WF_ENTRAINMENT_EN26_V6 — see FIXES
--      above. REGISTRATION stage content and TRAVEL's success-screen copy are still reproduced
--      verbatim, unchanged.
--   4. RESERVED_LINK workflow_variable_master row is assumed to already exist (it was inserted
--      idempotently by workflow-config-entrainment-en26-insert.sql, ON CONFLICT DO NOTHING) — not
--      re-verified against the live DB here.
-- ================================================

-- =====================================================
-- STEP 1: Soft-delete every currently-live PT_ENTRAINMENT workflow_configuration
-- Cascades deleted_at = NOW() from workflow_configuration -> workflow_stage and
-- workflow_configuration -> workflow_configuration_variable. Scoped by "deleted_at IS NULL"
-- throughout, so this is idempotent and safe to re-run.
-- =====================================================

UPDATE workflow_stage
SET deleted_at = NOW()
WHERE deleted_at IS NULL
  AND workflow_config_id IN (
      SELECT id FROM workflow_configuration
      WHERE program_type_key = 'PT_ENTRAINMENT'
        AND deleted_at IS NULL
  );

UPDATE workflow_configuration_variable
SET deleted_at = NOW()
WHERE deleted_at IS NULL
  AND workflow_config_id IN (
      SELECT id FROM workflow_configuration
      WHERE program_type_key = 'PT_ENTRAINMENT'
        AND deleted_at IS NULL
  );

UPDATE workflow_configuration
SET deleted_at = NOW()
WHERE program_type_key = 'PT_ENTRAINMENT'
  AND deleted_at IS NULL;

-- =====================================================
-- STEP 2: Recreate the workflow from scratch, reproducing WF_ENTRAINMENT_EN26_V6's
-- structure (Registration -> Payment -> Travel), minus its dead 4th GOODIES stage — see
-- header note above.
-- =====================================================

INSERT INTO workflow_configuration (
  workflow_key,
  workflow_name,
  program_type_key,
  program_type_id,
  workflow_version,
  lifecycle_status,
  description,
  data_query_template,
  registration_rules,
  initial_stage,
  created_by,
  updated_by,
  created_at,
  updated_at
) VALUES (
  'WF_ENTRAINMENT_V8',
  'Entrainment Program Registration Workflow',
  'PT_ENTRAINMENT',
  (SELECT id FROM program_type_v1 WHERE key = 'PT_ENTRAINMENT'),
  '2.0.1',
  'ACTIVE',
  'Entrainment program registration workflow with 3 stages (Basic Details, Payment, Travel) - refreshed from WF_ENTRAINMENT_EN26_V6',
  NULL, -- Will be generated from workflow variables
  '{
    "criteria": [
      {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
      {"operator": "OR", "conditions": [
        {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "completed"]},
        {"field": "isFreeSeat", "operator": "EQUALS", "value": true}
      ]},
      {"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"},
      {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}
    ],
    "message": "Registration is completed when basic details, payment, and travel information are all submitted."
  }'::jsonb,
  NULL,
  -2,
  -2,
  NOW(),
  NOW()
);

-- ================================================
-- Stage 1: REGISTRATION (Basic Details)
-- ================================================
INSERT INTO workflow_stage (
  workflow_config_id,
  stage_key,
  stage_name,
  stage_order,
  stage_category,
  is_optional,
  description,
  prerequisite_rules_config,
  execution_rules_config,
  action_buttons,
  completion_actions_config,
  created_by,
  updated_by,
  created_at,
  updated_at
) VALUES (
  (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_ENTRAINMENT_V8'),
  'REGISTRATION',
  'Basic Details',
  1,
  'FORM',
  false,
  'Seeker fills and submits basic registration details',
  '{
    "requiresAuth": true,
    "requiredStages": [],
    "conditions": [
      {"roles": ["ROLE_VIEWER", "ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "condition": {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"}, "message": "Login required to register"}
    ]
  }'::jsonb,
  '{
    "sections": [
      {
        "sectionKey": "FS_BASICDETAILS",
        "permissions": {
          "create": [{"roles": ["ROLE_VIEWER"], "condition": null}],
          "read": [{"roles": ["ALL"], "condition": null}],
          "update": [
            {"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
              {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"},
              {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]}
            ]}},
            {"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "condition": null}
          ],
          "delete": [{"roles": [], "condition": null}]
        }
      }
    ]
  }'::jsonb,
  '[
    {
      "actionKey": "CANCEL",
      "label": "Cancel",
      "type": "secondary",
      "icon": "close",
      "apiKey": null,
      "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "condition": null}],
      "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "showToast": false, "showSuccessScreen": false}]
    },
    {
      "actionKey": "SAVE_DRAFT",
      "label": "Save as Draft",
      "type": "secondary",
      "icon": "save",
      "apiKey": "SAVE_DRAFT",
      "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
        {"field": "allowsProxyRegistration", "operator": "EQUALS", "value": true},
        {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"}
      ]}}],
      "onSuccess": [{"roles": ["ROLE_VIEWER"], "showToast": true, "toast": {"message": "Draft saved successfully. You can continue later.", "type": "info"}, "showSuccessScreen": false}]
    },
    {
      "actionKey": "SUBMIT_REGISTRATION",
      "label": "Submit",
      "type": "primary",
      "icon": "send",
      "apiKey": "SUBMIT_REGISTRATION",
      "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"}}],
      "onSuccess": [{
        "roles": ["ROLE_VIEWER"],
        "showToast": false,
        "showSuccessScreen": false
      }]
    }
  ]'::jsonb,
  '{"conditional": true, "conditions": [{"when": {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"}, "then": {"stageStatus": "completed", "markStageComplete": true}}]}'::jsonb,
  -2,
  -2,
  NOW(),
  NOW()
);

-- ================================================
-- Stage 2: PAYMENT
-- ================================================
INSERT INTO workflow_stage (
  workflow_config_id,
  stage_key,
  stage_name,
  stage_order,
  stage_category,
  is_optional,
  description,
  prerequisite_rules_config,
  execution_rules_config,
  action_buttons,
  completion_actions_config,
  created_by,
  updated_by,
  created_at,
  updated_at
) VALUES (
  (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_ENTRAINMENT_V8'),
  'PAYMENT',
  'Payment',
  2,
  'FORM',
  false,
  'Process payment (online/offline) for Entrainment',
  '{
    "requiresAuth": true,
    "requiredStages": ["REGISTRATION"],
    "conditions": [
      {"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
        {"field": "requiresPayment", "operator": "EQUALS", "value": true},
        {"field": "isFreeSeat", "operator": "EQUALS", "value": false},
        {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
        {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
        {"operator": "OR", "conditions": [
          {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
          {"field": "reservedLink", "operator": "EQUALS", "value": true}
        ]},
        {
          "operator": "OR",
          "conditions": [
            {"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "failed"]},
            {"field": "paymentStatus", "operator": "IS_NULL"},
            {
              "operator": "AND",
              "conditions": [
                {"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"},
                {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}
              ]
            }
          ]
        }
      ]}, "message": "Basic details must be completed, not a free seat, registration must not be rejected, seat must be available or admin-released, and payment must be pending or have an active edit request"},
      {"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": {"operator": "AND", "conditions": [
        {"field": "requiresPayment", "operator": "EQUALS", "value": true},
        {"field": "isFreeSeat", "operator": "EQUALS", "value": false},
        {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
        {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
        {"operator": "OR", "conditions": [
          {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
          {"field": "reservedLink", "operator": "EQUALS", "value": true}
        ]}
      ]}, "message": "Basic details must be completed, not a free seat, registration must not be rejected, and seat must be available or admin-released"}
    ]
  }'::jsonb,
  '{
    "sections": [
      {
        "sectionKey": "FS_PAYMENTINVOICE",
        "permissions": {
          "create": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
            {"field": "requiresPayment", "operator": "EQUALS", "value": true},
            {"field": "isFreeSeat", "operator": "EQUALS", "value": false},
            {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
            {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
            {"operator": "OR", "conditions": [
              {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
              {"field": "reservedLink", "operator": "EQUALS", "value": true}
            ]}
          ]}}],
          "read": [{"roles": ["ALL"], "condition": null}],
          "update": [
            {
              "roles": ["ROLE_VIEWER"],
              "condition": {
                "operator": "AND",
                "conditions": [
                  {"field": "requiresPayment", "operator": "EQUALS", "value": true},
                  {"field": "isFreeSeat", "operator": "EQUALS", "value": false},
                  {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
                  {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
                  {"operator": "OR", "conditions": [
                    {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
                    {"field": "reservedLink", "operator": "EQUALS", "value": true}
                  ]},
                  {
                    "operator": "OR",
                    "conditions": [
                      {"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "failed"]},
                      {"field": "paymentStatus", "operator": "IS_NULL"},
                      {
                        "operator": "AND",
                        "conditions": [
                          {"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"},
                          {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}
                        ]
                      }
                    ]
                  }
                ]
              }
            },
            {"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": null}
          ],
          "delete": [{"roles": [], "condition": null}]
        }
      }
    ]
  }'::jsonb,
  '[
    {
      "actionKey": "CANCEL",
      "label": "Cancel",
      "type": "secondary",
      "icon": "close",
      "apiKey": null,
      "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "condition": null}],
      "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "showToast": false, "showSuccessScreen": false}]
    },
    {
      "actionKey": "MAKE_PAYMENT",
      "label": "submit",
      "type": "primary",
      "icon": "payment",
      "apiKey": "MAKE_PAYMENT",
      "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
        {"field": "requiresPayment", "operator": "EQUALS", "value": true},
        {"field": "isFreeSeat", "operator": "EQUALS", "value": false},
        {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"},
        {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
        {"operator": "OR", "conditions": [
          {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
          {"field": "reservedLink", "operator": "EQUALS", "value": true}
        ]},
        {
          "operator": "OR",
          "conditions": [
            {"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "failed"]},
            {"field": "paymentStatus", "operator": "IS_NULL"},
            {
              "operator": "AND",
              "conditions": [
                {"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"},
                {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}
              ]
            }
          ]
        }
      ]}}],
      "onSuccess": [{
        "roles": ["ROLE_VIEWER"],
        "showToast": false,
        "showSuccessScreen": true,
        "successScreenConfig": {
          "scenarios": [
            {
              "scenarioKey": "PAYMENT_EDIT_REQUESTED",
              "condition": {
                "operator": "AND",
                "conditions": [
                  {"field": "paymentMode", "operator": "EQUALS", "value": "offline"},
                  {"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"},
                  {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}
                ]
              },
              "screen": {
                "title": "{{programName}}",
                "message": "Your payment edit request for {{programName}} has been submitted. You can edit your payment details once the request is approved.",
                "icon": "info",
                "actions": [
                  {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null},
                  {"actionKey": "UPDATE_PAYMENT", "label": "Update Payment", "type": "secondary", "icon": null, "apiKey": "UPDATE_PAYMENT_DETAILS", "condition": null}
                ]
              }
            },
            {
              "scenarioKey": "ONLINE_PAYMENT_SUCCESS",
              "condition": {
                "operator": "AND",
                "conditions": [
                  {"field": "paymentMode", "operator": "EQUALS", "value": "online"},
                  {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "completed"]}
                ]
              },
              "screen": {
                "title": "Payment Completed!",
                "message": "Your payment for {{programName}} ({{programStartDate}} to {{programEndDate}}) has been completed successfully. You can proceed with travel details.",
                "icon": "check_circle",
                "actions": [
                  {"actionKey": "PROCEED_TO_TRAVEL", "label": "Proceed to Travel", "type": "primary", "icon": "flight", "apiKey": null, "condition": {"field": "involvesTravel", "operator": "EQUALS", "value": true}},
                  {"actionKey": "DOWNLOAD_INVOICE", "label": "Download Invoice", "type": "secondary", "icon": "download", "apiKey": "DOWNLOAD_INVOICE", "condition": {"field": "paymentStatus", "operator": "EQUALS", "value": "online_completed"}},
                  {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null}
                ]
              }
            },
            {
              "scenarioKey": "OFFLINE_PAYMENT_CHEQUE",
              "condition": {
                "operator": "AND",
                "conditions": [
                  {"field": "paymentMode", "operator": "EQUALS", "value": "offline"},
                  {"field": "offlinePaymentMethod", "operator": "EQUALS", "value": "Cheque"}
                ]
              },
              "screen": {
                "title": "Payment Submitted!",
                "message": "We acknowledge your payment towards {{programName}} ({{programStartDate}} to {{programEndDate}}). Note: cheques are subject to realization. You can proceed with travel details.",
                "icon": "check_circle",
                "actions": [
                  {"actionKey": "PROCEED_TO_TRAVEL", "label": "Proceed to Travel", "type": "primary", "icon": "flight", "apiKey": null, "condition": {"field": "involvesTravel", "operator": "EQUALS", "value": true}},
                  {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null}
                ]
              }
            },
            {
              "scenarioKey": "OFFLINE_PAYMENT_OTHER",
              "condition": {
                "operator": "AND",
                "conditions": [
                  {"field": "paymentMode", "operator": "EQUALS", "value": "offline"},
                  {"field": "offlinePaymentMethod", "operator": "NOT_EQUALS", "value": "Cheque"}
                ]
              },
              "screen": {
                "title": "Payment Submitted!",
                "message": "We acknowledge your payment towards {{programName}} ({{programStartDate}} to {{programEndDate}}). You can proceed with travel details.",
                "icon": "check_circle",
                "actions": [
                  {"actionKey": "PROCEED_TO_TRAVEL", "label": "Proceed to Travel", "type": "primary", "icon": "flight", "apiKey": null, "condition": {"field": "involvesTravel", "operator": "EQUALS", "value": true}},
                  {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null}
                ]
              }
            }
          ],
          "defaultScreen": {
            "title": "Payment Submitted!",
            "message": "Your payment for {{programName}} has been submitted successfully.",
            "icon": "check_circle",
            "actions": [
              {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null}
            ]
          }
        }
      }]
    }
  ]'::jsonb,
  '{"conditional": true, "conditions": [{"when": {"operator": "OR", "conditions": [
    {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "completed"]},
    {"field": "isFreeSeat", "operator": "EQUALS", "value": true}
  ]}, "then": {"stageStatus": "completed", "markStageComplete": true}}]}'::jsonb,
  -2,
  -2,
  NOW(),
  NOW()
);

-- ================================================
-- Stage 3: TRAVEL
-- ================================================
INSERT INTO workflow_stage (
  workflow_config_id,
  stage_key,
  stage_name,
  stage_order,
  stage_category,
  is_optional,
  description,
  prerequisite_rules_config,
  execution_rules_config,
  action_buttons,
  completion_actions_config,
  created_by,
  updated_by,
  created_at,
  updated_at
) VALUES (
  (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_ENTRAINMENT_V8'),
  'TRAVEL',
  'Travel',
  3,
  'FORM',
  false,
  'Submit travel information and plan for Entrainment',
  '{
    "requiresAuth": true,
    "requiredStages": ["REGISTRATION", "PAYMENT"],
    "conditions": [
      {"roles": ["ROLE_VIEWER", "ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": {"operator": "AND", "conditions": [
        {"field": "involvesTravel", "operator": "EQUALS", "value": true},
        {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
        {"operator": "OR", "conditions": [
          {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "offline_pending", "completed"]},
          {"field": "isFreeSeat", "operator": "EQUALS", "value": true}
        ]},
        {"operator": "OR", "conditions": [
          {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
          {"field": "reservedLink", "operator": "EQUALS", "value": true}
        ]}
      ]}, "message": "Payment must be completed or seat must be free, registration must not be rejected, and not waitlisted (or admin-released)"}
    ]
  }'::jsonb,
  '{
    "sections": [
      {
        "sectionKey": "FS_TRAVELPLAN",
        "permissions": {
          "create": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
            {"field": "involvesTravel", "operator": "EQUALS", "value": true},
            {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
            {"operator": "OR", "conditions": [
              {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "offline_pending", "completed"]},
              {"field": "isFreeSeat", "operator": "EQUALS", "value": true}
            ]},
            {"operator": "OR", "conditions": [
              {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
              {"field": "reservedLink", "operator": "EQUALS", "value": true}
            ]}
          ]}}],
          "read": [{"roles": ["ALL"], "condition": null}],
          "update": [
            {"roles": ["ROLE_VIEWER"], "condition": {"field": "travelPlanStatus", "operator": "NOT_EQUALS", "value": "completed"}},
            {"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": null}
          ],
          "delete": [{"roles": [], "condition": null}]
        }
      }
    ]
  }'::jsonb,
  '[
    {
      "actionKey": "CANCEL",
      "label": "Cancel",
      "type": "secondary",
      "icon": "close",
      "apiKey": null,
      "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "condition": null}],
      "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "showToast": false, "showSuccessScreen": false}]
    },
    {
      "actionKey": "SAVE_TRAVEL",
      "label": "submit",
      "type": "primary",
      "icon": "send",
      "apiKey": "SAVE_TRAVEL",
      "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [
        {"field": "involvesTravel", "operator": "EQUALS", "value": true},
        {"field": "registrationStatus", "operator": "NOT_IN", "value": ["rejected"]},
        {"operator": "OR", "conditions": [
          {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "offline_pending", "completed"]},
          {"field": "isFreeSeat", "operator": "EQUALS", "value": true}
        ]},
        {"operator": "OR", "conditions": [
          {"field": "registrationStatus", "operator": "NOT_IN", "value": ["waitlisted"]},
          {"field": "reservedLink", "operator": "EQUALS", "value": true}
        ]}
      ]}}],
      "onSuccess": [{
        "roles": ["ROLE_VIEWER"],
        "showToast": true,
        "toast": {"message": "Travel details submitted successfully!", "type": "success"},
        "showSuccessScreen": true,
        "successScreen": {
          "title": "Registration Complete!",
          "message": "Your registration for {{programName}} is now complete. We look forward to seeing you at {{programVenue}} from {{programStartDate}} to {{programEndDate}}!",
          "icon": "check_circle",
          "actions": [
            {"actionKey": "HOME", "label": "Go to Home", "type": "secondary", "icon": "home", "apiKey": null, "condition": null}
          ]
        }
      }]
    }
  ]'::jsonb,
  '{"conditional": true, "conditions": [{"when": {"operator": "AND", "conditions": [
    {"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"},
    {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}
  ]}, "then": {"stageStatus": "completed", "markStageComplete": true}}]}'::jsonb,
  -2,
  -2,
  NOW(),
  NOW()
);

-- NOTE: there is deliberately no separate "GOODIES" stage here (unlike WF_ENTRAINMENT_EN26_V6,
-- which had one pointing at a "FS_GOODIES" section). Per confirmation, goodies and travel are
-- merged in the actual template: database/entrainment-migrations-v2(2026-08-10)/03template-refresh.sql
-- STEP 6 injects goodiesTshirtApplicable/goodiesTshirtSize directly into FS_TRAVELPLAN — there
-- is no FS_GOODIES section to grant permissions on. EN26 V6's GOODIES stage was therefore dead
-- (its "sections":[{"sectionKey":"FS_GOODIES"...}] permission block could never match any real
-- section), so it's dropped here rather than reproduced. The goodies fields are covered by
-- Stage 3's FS_TRAVELPLAN permissions/SAVE_TRAVEL action above, submitted together with travel
-- details in one step. GOODIES_STATUS / PROGRAM_HAS_GOODIES are NOT linked as workflow
-- variables below either — removed along with the stage, so no goodies traces remain here.

-- ================================================
-- Link Variables to the refreshed Entrainment workflow
-- Same variable set WF_ENTRAINMENT_EN26_V6 linked (see
-- database/workflow-config-entrainment-en26-insert.sql).
-- ================================================
DO $$
DECLARE
    v_workflow_id INT;
    v_var_id INT;
    v_order INT := 1;
BEGIN
    SELECT id INTO v_workflow_id FROM workflow_configuration WHERE workflow_key = 'WF_ENTRAINMENT_V8' LIMIT 1;

    IF v_workflow_id IS NOT NULL THEN
        FOR v_var_id IN
            SELECT id FROM workflow_variable_master
            WHERE variable_key IN (
              'REGISTRATION_ID',
              'USER_ID',
              'PROGRAM_ID',
              'REGISTRATION_STATUS',
              'BASIC_DETAILS_STATUS',
              'PAYMENT_STATUS',
              'PAYMENT_MODE',
              'EDIT_REQUEST_STATUS',
              'TRAVEL_INFO_STATUS',
              'TRAVEL_PLAN_STATUS',
              'PRO_FORMA_INVOICE_PDF_URL',
              'IS_FREE_SEAT_COMPUTED',
              'IS_WAITLISTED',
              'RESERVED_LINK',
              'WAITLIST_POSITION',
              'INVOICE_GENERATED',
              'INVOICE_PDF_URL',
              'INVOICE_STATUS',
              'REGISTRATION_NUMBER',
              'SEEKER_NAME',
              'SEEKER_EMAIL',
              'SEEKER_PHONE',
              'PROGRAM_FEE',
              'PROGRAM_NAME',
              'PROGRAM_START_DATE',
              'PROGRAM_END_DATE',
              'PROGRAM_VENUE',
              'APPROVAL_STATUS',
              'PROGRAM_REQUIRES_PAYMENT',
              'PROGRAM_INVOLVES_TRAVEL',
              'PROGRAM_REQUIRES_APPROVAL',
              'PROGRAM_ALLOWS_PROXY_REGISTRATION',
              'PROGRAM_HAS_TERMS'
            )
            ORDER BY execution_order, variable_key
        LOOP
            INSERT INTO workflow_configuration_variable
            (workflow_config_id, variable_master_id, variable_order, is_required, created_by, updated_by)
            VALUES (v_workflow_id, v_var_id, v_order, false, -2, -2)
            ON CONFLICT DO NOTHING;
            v_order := v_order + 1;
        END LOOP;

        RAISE NOTICE 'Linked % variables to refreshed Entrainment workflow (ID: %)', v_order - 1, v_workflow_id;
    ELSE
        RAISE NOTICE 'Refreshed Entrainment workflow not found, skipping variable linking';
    END IF;
END $$;

-- =====================================================
-- STEP 3: Repoint every PT_ENTRAINMENT program_v1 row that was still pointing at one of the
-- just-soft-deleted workflow_configuration rows onto the new one. workflow_id is a NOT NULL FK
-- on program_v1, so this must happen before the migration is considered complete.
-- =====================================================

UPDATE program_v1
SET workflow_id = (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_ENTRAINMENT_V8')
WHERE program_type_id = (SELECT id FROM program_type_v1 WHERE key = 'PT_ENTRAINMENT')
  AND workflow_id IN (
      SELECT id FROM workflow_configuration
      WHERE program_type_key = 'PT_ENTRAINMENT'
        AND deleted_at IS NOT NULL
  );

-- =====================================================
-- VERIFICATION QUERIES (commented out — uncomment to run manually after migration)
-- =====================================================

-- -- Confirm exactly one live workflow_configuration remains for PT_ENTRAINMENT
-- SELECT id, workflow_key, workflow_version, lifecycle_status, created_at, deleted_at
-- FROM workflow_configuration
-- WHERE program_type_key = 'PT_ENTRAINMENT'
-- ORDER BY created_at DESC;

-- -- Stage + variable counts on the new live workflow
-- SELECT
--   wc.id, wc.workflow_key,
--   COUNT(DISTINCT ws.id)  AS live_stages,
--   COUNT(DISTINCT wcv.id) AS live_variables
-- FROM workflow_configuration wc
-- LEFT JOIN workflow_stage ws ON ws.workflow_config_id = wc.id AND ws.deleted_at IS NULL
-- LEFT JOIN workflow_configuration_variable wcv ON wcv.workflow_config_id = wc.id AND wcv.deleted_at IS NULL
-- WHERE wc.workflow_key = 'WF_ENTRAINMENT_V8'
-- GROUP BY wc.id, wc.workflow_key;

-- -- Confirm no live PT_ENTRAINMENT program_v1 row still points at a deleted workflow_configuration
-- SELECT p.id, p.workflow_id
-- FROM program_v1 p
-- INNER JOIN workflow_configuration wc ON wc.id = p.workflow_id
-- WHERE p.program_type_id = (SELECT id FROM program_type_v1 WHERE key = 'PT_ENTRAINMENT')
--   AND wc.deleted_at IS NOT NULL; -- should return 0 rows
