-- name: InsertDiagnosticEvent :one
-- Records one client-reported diagnostic event. The writer validates the
-- `kind` category against its whitelist before this runs; the CHECK
-- constraint is the belt-and-braces guard. payload carries the finer
-- event discriminator + all event-specific fields. Returns received_at
-- so the caller can confirm ingest.
INSERT INTO diagnostic_events (
    user_id, client_id, app_version, os_version, kind, payload, occurred_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, received_at;

-- name: ListAdminDiagnostics :many
-- Admin timeline query. All filters are optional (NULL = no filter):
-- account (user_id), device (client_id), category (kind), and the
-- occurred_at window (from_ts/to_ts). Newest-first; the SPA reverses for
-- a chronological timeline / export. Joined with users for the username
-- so the view renders without a second round-trip.
SELECT
    de.id          AS id,
    de.user_id     AS user_id,
    u.username     AS username,
    de.client_id   AS client_id,
    de.app_version AS app_version,
    de.os_version  AS os_version,
    de.kind        AS kind,
    de.payload     AS payload,
    de.occurred_at AS occurred_at,
    de.received_at AS received_at
FROM diagnostic_events de
JOIN users u ON u.id = de.user_id
WHERE (sqlc.narg(user_id)::uuid   IS NULL OR de.user_id   = sqlc.narg(user_id)::uuid)
  AND (sqlc.narg(client_id)::text IS NULL OR de.client_id = sqlc.narg(client_id)::text)
  AND (sqlc.narg(kind)::text      IS NULL OR de.kind      = sqlc.narg(kind)::text)
  AND (sqlc.narg(from_ts)::timestamptz IS NULL
       OR de.occurred_at >= sqlc.narg(from_ts)::timestamptz)
  AND (sqlc.narg(to_ts)::timestamptz IS NULL
       OR de.occurred_at <= sqlc.narg(to_ts)::timestamptz)
ORDER BY de.occurred_at DESC
LIMIT sqlc.arg(lim)::int OFFSET sqlc.arg(off)::int;

-- name: ListDiagnosticDevices :many
-- Distinct devices that have reported, for the admin device filter +
-- "who is currently reporting" overview. Optionally scoped to one account.
SELECT
    de.client_id            AS client_id,
    de.user_id              AS user_id,
    u.username              AS username,
    max(de.app_version)::text        AS app_version,
    max(de.os_version)::text         AS os_version,
    max(de.occurred_at)::timestamptz AS last_seen,
    count(*)                         AS event_count
FROM diagnostic_events de
JOIN users u ON u.id = de.user_id
WHERE (sqlc.narg(user_id)::uuid IS NULL OR de.user_id = sqlc.narg(user_id)::uuid)
GROUP BY de.client_id, de.user_id, u.username
ORDER BY last_seen DESC;

-- name: GcPruneDiagnostics :execrows
-- Retention sweep for the gc worker. Deletes diagnostic_events older
-- than 30 days by server clock (received_at) so a skewed client clock
-- can't keep rows alive. Matches the other gc lifecycle sweeps'
-- hardcoded-threshold style; diagnostics are debug telemetry, not user
-- data, and 30 days is ample to investigate a live incident after the
-- fact. Returns the affected row count for the sweep log line.
DELETE FROM diagnostic_events WHERE received_at < now() - INTERVAL '30 days';
