CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE TABLE IF NOT EXISTS schema_migrations (
  id text PRIMARY KEY,
  applied_at timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS agents (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_user_id text NOT NULL,
  owner_email text,
  display_name text NOT NULL,
  avatar_url text,
  status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled', 'revoked')),
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS agents_owner_user_id_idx ON agents(owner_user_id);
CREATE INDEX IF NOT EXISTS agents_owner_email_idx ON agents(owner_email);

CREATE TABLE IF NOT EXISTS agent_grants (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
  workspace_slug text NOT NULL,
  project_id text NOT NULL DEFAULT '',
  scopes text[] NOT NULL DEFAULT '{}',
  mode text NOT NULL DEFAULT 'voluntary' CHECK (mode IN ('voluntary', 'reporting')),
  created_by_user_id text NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE(agent_id, workspace_slug, project_id)
);

CREATE INDEX IF NOT EXISTS agent_grants_agent_id_idx ON agent_grants(agent_id);
CREATE INDEX IF NOT EXISTS agent_grants_workspace_slug_idx ON agent_grants(workspace_slug);

CREATE TABLE IF NOT EXISTS agent_tokens (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
  token_hash text NOT NULL UNIQUE,
  name text NOT NULL,
  status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'revoked', 'expired')),
  expires_at timestamptz,
  last_used_at timestamptz,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS agent_tokens_agent_id_idx ON agent_tokens(agent_id);
CREATE INDEX IF NOT EXISTS agent_tokens_status_idx ON agent_tokens(status);

CREATE TABLE IF NOT EXISTS pairing_codes (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
  code_hash text NOT NULL UNIQUE,
  status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'used', 'expired', 'revoked')),
  expires_at timestamptz NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  used_at timestamptz
);

CREATE INDEX IF NOT EXISTS pairing_codes_agent_id_idx ON pairing_codes(agent_id);
CREATE INDEX IF NOT EXISTS pairing_codes_status_idx ON pairing_codes(status);

CREATE TABLE IF NOT EXISTS agent_audit_events (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  agent_id uuid REFERENCES agents(id) ON DELETE SET NULL,
  event_type text NOT NULL,
  actor_user_id text,
  metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS agent_audit_events_agent_id_idx ON agent_audit_events(agent_id);
CREATE INDEX IF NOT EXISTS agent_audit_events_event_type_idx ON agent_audit_events(event_type);

CREATE TABLE IF NOT EXISTS idempotency_keys (
  key text PRIMARY KEY,
  agent_id uuid REFERENCES agents(id) ON DELETE CASCADE,
  request_hash text NOT NULL,
  response_body jsonb NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  expires_at timestamptz NOT NULL
);

CREATE INDEX IF NOT EXISTS idempotency_keys_expires_at_idx ON idempotency_keys(expires_at);
