-- Phase 4.2 — Datto RMM Overshell evidence pipeline.
--
-- Two tables:
--   1. rmm_settings — singleton row caching the discovered Overshell
--      component_uid + variable_name. Avoids re-discovering on every dispatch.
--   2. rmm_executions — full lifecycle of every Overshell job Pulse triggers.
--      Forever-retained: stdout/stderr (redacted), parsed evidence, audit
--      linkage, target/asset linkage.

CREATE TABLE IF NOT EXISTS rmm_settings (
  id                          BOOLEAN PRIMARY KEY DEFAULT true CHECK (id),
  overshell_component_uid     TEXT,
  overshell_component_name    TEXT,
  -- The variable name the Overshell component expects the script body in.
  -- Default 'CommandLine' matches the Datto-provided "Run Command" component;
  -- Wulf's custom Overshell may use a different name (e.g. 'Script') —
  -- adjustable via /admin/rmm-overshell.
  overshell_variable_name     TEXT NOT NULL DEFAULT 'CommandLine',
  discovered_at               TIMESTAMPTZ,
  updated_at                  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
INSERT INTO rmm_settings (id) VALUES (true) ON CONFLICT DO NOTHING;

CREATE TABLE IF NOT EXISTS rmm_executions (
  id                       UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  -- Script library identifiers (script bodies are version-controlled in code).
  script_id                TEXT NOT NULL,
  script_version           INT NOT NULL DEFAULT 1,
  -- Target resolution.
  target_type              TEXT NOT NULL
                             CHECK (target_type IN ('site_anchor','asset_self')),
  target_device_uid        TEXT NOT NULL,
  target_hostname          TEXT,
  target_company_id        BIGINT,
  -- Optional links back to the audit / asset the user clicked from.
  triggered_by_audit_id    UUID REFERENCES itglue_asset_audits(id) ON DELETE SET NULL,
  asset_type               TEXT
                             CHECK (asset_type IS NULL OR asset_type IN ('flexible_asset','configuration')),
  asset_id                 BIGINT,
  -- Datto job tracking.
  job_uid                  TEXT,
  job_name                 TEXT NOT NULL,
  variables                JSONB NOT NULL,
  status                   TEXT NOT NULL DEFAULT 'queued'
                             CHECK (status IN ('queued','running','complete','failed','timeout')),
  exit_code                INT,
  raw_stdout               TEXT,
  raw_stderr               TEXT,
  parsed_evidence          JSONB,
  parse_error              TEXT,
  error_message            TEXT,
  performed_by_user_id     TEXT REFERENCES "user"(id) ON DELETE SET NULL,
  queued_at                TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  started_at               TIMESTAMPTZ,
  completed_at             TIMESTAMPTZ,
  -- Hard timeout marker. The poller will mark a still-running execution as
  -- timeout once NOW() > timeout_at and stop polling.
  timeout_at               TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '5 minutes'
);

CREATE INDEX IF NOT EXISTS ix_rmm_executions_status
  ON rmm_executions (status, queued_at);
CREATE INDEX IF NOT EXISTS ix_rmm_executions_target_device
  ON rmm_executions (target_device_uid, queued_at DESC);
CREATE INDEX IF NOT EXISTS ix_rmm_executions_company
  ON rmm_executions (target_company_id, queued_at DESC);
CREATE INDEX IF NOT EXISTS ix_rmm_executions_audit
  ON rmm_executions (triggered_by_audit_id);
CREATE INDEX IF NOT EXISTS ix_rmm_executions_asset
  ON rmm_executions (asset_type, asset_id, queued_at DESC)
  WHERE asset_type IS NOT NULL;

-- The audit-context loader pulls the latest successful execution per
-- (company, script). Partial index keeps the lookup fast even as the table
-- grows.
CREATE INDEX IF NOT EXISTS ix_rmm_executions_latest_success
  ON rmm_executions (target_company_id, script_id, completed_at DESC)
  WHERE status = 'complete';

CREATE INDEX IF NOT EXISTS ix_rmm_executions_user_window
  ON rmm_executions (performed_by_user_id, queued_at)
  WHERE performed_by_user_id IS NOT NULL;

COMMENT ON TABLE rmm_executions IS
  'Every Overshell job Pulse dispatched to Datto RMM. status: queued (we '
  'inserted the row but have not yet called runQuickJob), running (job_uid '
  'returned by Datto), complete (poller saw stdout), failed (exit_code != 0 '
  'or HTTP failure), timeout (still running past timeout_at).';
