CREATE TABLE IF NOT EXISTS gateway_execution_pools (
  pool_id text PRIMARY KEY,
  labels jsonb NOT NULL DEFAULT '{}'::jsonb,
  capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
  state text NOT NULL DEFAULT 'active',
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT gateway_execution_pools_id_check
    CHECK (pool_id ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$'),
  CONSTRAINT gateway_execution_pools_state_check
    CHECK (state IN ('active', 'draining', 'disabled')),
  CONSTRAINT gateway_execution_pools_labels_object_check
    CHECK (jsonb_typeof(labels) = 'object'),
  CONSTRAINT gateway_execution_pools_capabilities_object_check
    CHECK (jsonb_typeof(capabilities) = 'object')
);

INSERT INTO gateway_execution_pools (pool_id, labels)
VALUES ('legacy-default', '{"migration":"legacy"}'::jsonb)
ON CONFLICT (pool_id) DO NOTHING;

INSERT INTO gateway_execution_pools (pool_id, labels)
SELECT DISTINCT site, jsonb_build_object('legacy_site', site)
FROM gateway_worker_instances
WHERE NULLIF(site, '') IS NOT NULL
ON CONFLICT (pool_id) DO NOTHING;

ALTER TABLE gateway_worker_instances
  ADD COLUMN pool_id text DEFAULT 'legacy-default',
  ADD COLUMN worker_id text DEFAULT '',
  ADD COLUMN endpoint text DEFAULT '',
  ADD COLUMN orchestrator_instance_ref text DEFAULT '',
  ADD COLUMN labels jsonb DEFAULT '{}'::jsonb,
  ADD COLUMN capabilities jsonb DEFAULT '{}'::jsonb,
  ADD COLUMN protocol_version text DEFAULT 'v1';

UPDATE gateway_worker_instances
SET pool_id = site
WHERE NULLIF(site, '') IS NOT NULL
  AND pool_id = 'legacy-default';

UPDATE gateway_worker_instances
SET worker_id = instance_id
WHERE worker_id = '';

UPDATE gateway_worker_instances
SET orchestrator_instance_ref = pod_name
WHERE orchestrator_instance_ref = ''
  AND NULLIF(pod_name, '') IS NOT NULL;

ALTER TABLE gateway_worker_instances
  ADD CONSTRAINT gateway_worker_instances_pool_fk
    FOREIGN KEY (pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT,
  ADD CONSTRAINT gateway_worker_instances_routing_fields_not_null_check
    CHECK (num_nonnulls(pool_id, worker_id, endpoint, orchestrator_instance_ref, labels, capabilities, protocol_version) = 7) NOT VALID,
  ADD CONSTRAINT gateway_worker_instances_labels_object_check
    CHECK (jsonb_typeof(labels) = 'object') NOT VALID,
  ADD CONSTRAINT gateway_worker_instances_capabilities_object_check
    CHECK (jsonb_typeof(capabilities) = 'object') NOT VALID;

ALTER TABLE gateway_worker_instances
  VALIDATE CONSTRAINT gateway_worker_instances_routing_fields_not_null_check;

ALTER TABLE gateway_worker_instances
  VALIDATE CONSTRAINT gateway_worker_instances_labels_object_check;

ALTER TABLE gateway_worker_instances
  VALIDATE CONSTRAINT gateway_worker_instances_capabilities_object_check;

CREATE INDEX IF NOT EXISTS idx_worker_instances_pool_heartbeat
  ON gateway_worker_instances(pool_id, status, heartbeat_at, instance_id);

CREATE TABLE IF NOT EXISTS gateway_route_health (
  pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE,
  route_profile_key text NOT NULL,
  state text NOT NULL DEFAULT 'unknown',
  success_rate double precision NOT NULL DEFAULT 0,
  connect_tls_p95_ms bigint NOT NULL DEFAULT 0,
  first_byte_p95_ms bigint NOT NULL DEFAULT 0,
  upload_bytes_per_second double precision NOT NULL DEFAULT 0,
  jitter_p95_ms bigint NOT NULL DEFAULT 0,
  consecutive_failures integer NOT NULL DEFAULT 0,
  consecutive_successes integer NOT NULL DEFAULT 0,
  sample_count integer NOT NULL DEFAULT 0,
  sampled_at timestamptz NOT NULL,
  expires_at timestamptz NOT NULL,
  updated_at timestamptz NOT NULL DEFAULT now(),
  PRIMARY KEY (pool_id, route_profile_key),
  CONSTRAINT gateway_route_health_state_check
    CHECK (state IN ('healthy', 'degraded', 'unreachable', 'unknown')),
  CONSTRAINT gateway_route_health_values_check
    CHECK (
      success_rate >= 0 AND success_rate <= 1
      AND connect_tls_p95_ms >= 0
      AND first_byte_p95_ms >= 0
      AND upload_bytes_per_second >= 0
      AND jitter_p95_ms >= 0
      AND consecutive_failures >= 0
      AND consecutive_successes >= 0
      AND sample_count >= 0
      AND expires_at >= sampled_at
    )
);

CREATE INDEX IF NOT EXISTS idx_gateway_route_health_fresh
  ON gateway_route_health(route_profile_key, expires_at, state, pool_id);

CREATE TABLE IF NOT EXISTS gateway_route_preferences (
  route_profile_key text PRIMARY KEY,
  current_pool_id text NOT NULL DEFAULT '',
  current_since timestamptz,
  challenger_pool_id text NOT NULL DEFAULT '',
  challenger_wins integer NOT NULL DEFAULT 0,
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT gateway_route_preferences_wins_check CHECK (challenger_wins >= 0)
);

CREATE TABLE IF NOT EXISTS gateway_route_probe_requests (
  route_profile_key text PRIMARY KEY,
  requested_at timestamptz NOT NULL DEFAULT now(),
  expires_at timestamptz NOT NULL DEFAULT now() + interval '30 seconds'
);

CREATE INDEX IF NOT EXISTS idx_gateway_route_probe_requests_due
  ON gateway_route_probe_requests(expires_at, requested_at);

CREATE TABLE IF NOT EXISTS gateway_pool_capacity_desires (
  pool_id text PRIMARY KEY REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE,
  desired integer NOT NULL,
  reason text NOT NULL DEFAULT '',
  valid_until timestamptz NOT NULL,
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT gateway_pool_capacity_desires_value_check CHECK (desired >= 0)
);

CREATE TABLE IF NOT EXISTS gateway_worker_execution_leases (
  lease_id uuid PRIMARY KEY,
  task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
  pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT,
  worker_id text NOT NULL,
  instance_id text NOT NULL REFERENCES gateway_worker_instances(instance_id) ON DELETE CASCADE,
  nonce_hash text NOT NULL UNIQUE,
  state text NOT NULL DEFAULT 'reserved',
  expires_at timestamptz NOT NULL,
  released_at timestamptz,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT gateway_worker_execution_leases_state_check
    CHECK (state IN ('reserved', 'running', 'released', 'expired'))
);

CREATE INDEX IF NOT EXISTS idx_worker_execution_leases_active
  ON gateway_worker_execution_leases(pool_id, instance_id, expires_at)
  WHERE released_at IS NULL;

ALTER TABLE gateway_tasks
  ADD COLUMN assigned_pool_id text,
  ADD COLUMN assigned_worker_id text,
  ADD COLUMN route_profile_key text,
  ADD COLUMN routing_platform_id uuid,
  ADD COLUMN routing_platform_model_id uuid,
  ADD COLUMN routing_version text,
  ADD COLUMN routing_reason text,
  ADD COLUMN routing_snapshot jsonb,
  ADD COLUMN submission_state text DEFAULT 'not_started';

ALTER TABLE gateway_tasks
  ADD CONSTRAINT gateway_tasks_assigned_pool_fk
    FOREIGN KEY (assigned_pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE SET NULL,
  ADD CONSTRAINT gateway_tasks_routing_platform_fk
    FOREIGN KEY (routing_platform_id) REFERENCES integration_platforms(id) ON DELETE SET NULL,
  ADD CONSTRAINT gateway_tasks_routing_platform_model_fk
    FOREIGN KEY (routing_platform_model_id) REFERENCES platform_models(id) ON DELETE SET NULL,
  ADD CONSTRAINT gateway_tasks_routing_snapshot_object_check
    CHECK (routing_snapshot IS NULL OR jsonb_typeof(routing_snapshot) = 'object') NOT VALID,
  ADD CONSTRAINT gateway_tasks_submission_state_not_null_check
    CHECK (num_nonnulls(submission_state) = 1) NOT VALID,
  ADD CONSTRAINT gateway_tasks_submission_state_check
    CHECK (submission_state IN ('not_started', 'submitting', 'submitted', 'submission_confirmation_pending', 'completed')) NOT VALID;

ALTER TABLE gateway_tasks
  VALIDATE CONSTRAINT gateway_tasks_submission_state_not_null_check;

ALTER TABLE gateway_tasks
  VALIDATE CONSTRAINT gateway_tasks_routing_snapshot_object_check;

ALTER TABLE gateway_tasks
  VALIDATE CONSTRAINT gateway_tasks_submission_state_check;

CREATE INDEX IF NOT EXISTS idx_gateway_tasks_assigned_pool_queue
  ON gateway_tasks(assigned_pool_id, status, next_run_at, priority, created_at)
  WHERE async_mode = true AND status = 'queued';
