-- Migration 058: Create Duo Security tables
-- Stores data from both Accounts API (child accounts) and Admin API (users, phones, auth logs, groups, integrations)

-- ── duo_accounts ─────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_accounts (
  id                    SERIAL PRIMARY KEY,
  account_id            VARCHAR(20) NOT NULL UNIQUE,
  name                  VARCHAR(255),
  api_hostname          VARCHAR(255),
  autotask_company_id   BIGINT REFERENCES companies(id) ON DELETE SET NULL,
  user_count            INTEGER DEFAULT 0,
  integration_count     INTEGER DEFAULT 0,
  edition               VARCHAR(50),
  is_parent             BOOLEAN DEFAULT false,
  synced_at             TIMESTAMP WITHOUT TIME ZONE,
  created_at            TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_duo_accounts_company ON duo_accounts(autotask_company_id);
CREATE INDEX IF NOT EXISTS idx_duo_accounts_is_parent ON duo_accounts(is_parent);

-- ── duo_users ────────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_users (
  id                    SERIAL PRIMARY KEY,
  user_id               VARCHAR(30) NOT NULL UNIQUE,
  duo_account_id        VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
  username              VARCHAR(255),
  email                 VARCHAR(255),
  realname              VARCHAR(255),
  status                VARCHAR(50),
  is_enrolled           BOOLEAN DEFAULT false,
  last_login            TIMESTAMP WITHOUT TIME ZONE,
  last_directory_sync   TIMESTAMP WITHOUT TIME ZONE,
  created               TIMESTAMP WITHOUT TIME ZONE,
  notes                 TEXT,
  phones_count          INTEGER DEFAULT 0,
  groups                JSONB,
  aliases               JSONB,
  enable_auto_prompt    BOOLEAN DEFAULT true,
  synced_at             TIMESTAMP WITHOUT TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_duo_users_account ON duo_users(duo_account_id);
CREATE INDEX IF NOT EXISTS idx_duo_users_status ON duo_users(status);
CREATE INDEX IF NOT EXISTS idx_duo_users_email ON duo_users(email);
CREATE INDEX IF NOT EXISTS idx_duo_users_enrolled ON duo_users(is_enrolled);

-- ── duo_phones ───────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_phones (
  id                    SERIAL PRIMARY KEY,
  phone_id              VARCHAR(30) NOT NULL UNIQUE,
  duo_account_id        VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
  name                  VARCHAR(255),
  number                VARCHAR(50),
  type                  VARCHAR(50),
  platform              VARCHAR(50),
  model                 VARCHAR(255),
  os_version            VARCHAR(50),
  app_version           VARCHAR(50),
  activated             BOOLEAN DEFAULT false,
  last_seen             TIMESTAMP WITHOUT TIME ZONE,
  capabilities          JSONB,
  users                 JSONB,
  synced_at             TIMESTAMP WITHOUT TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_duo_phones_account ON duo_phones(duo_account_id);

-- ── duo_auth_logs ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_auth_logs (
  id                        SERIAL PRIMARY KEY,
  txid                      VARCHAR(50) NOT NULL UNIQUE,
  duo_account_id            VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
  timestamp                 TIMESTAMP WITHOUT TIME ZONE NOT NULL,
  user_name                 VARCHAR(255),
  user_id                   VARCHAR(30),
  factor                    VARCHAR(50),
  result                    VARCHAR(50),
  reason                    VARCHAR(255),
  application_name          VARCHAR(255),
  application_key           VARCHAR(50),
  access_device_ip          INET,
  access_device_location    JSONB,
  auth_device_ip            INET,
  auth_device_name          VARCHAR(255),
  event_type                VARCHAR(50),
  synced_at                 TIMESTAMP WITHOUT TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_account ON duo_auth_logs(duo_account_id);
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_timestamp ON duo_auth_logs(timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_result ON duo_auth_logs(result);
CREATE INDEX IF NOT EXISTS idx_duo_auth_logs_user ON duo_auth_logs(user_name);

-- ── duo_groups ───────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_groups (
  id                    SERIAL PRIMARY KEY,
  group_id              VARCHAR(30) NOT NULL UNIQUE,
  duo_account_id        VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
  name                  VARCHAR(255),
  description           TEXT,
  member_count          INTEGER DEFAULT 0,
  status                VARCHAR(50),
  synced_at             TIMESTAMP WITHOUT TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_duo_groups_account ON duo_groups(duo_account_id);

-- ── duo_integrations ─────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS duo_integrations (
  id                    SERIAL PRIMARY KEY,
  integration_key       VARCHAR(50) NOT NULL UNIQUE,
  duo_account_id        VARCHAR(20) NOT NULL REFERENCES duo_accounts(account_id) ON DELETE CASCADE,
  name                  VARCHAR(255),
  type                  VARCHAR(100),
  enabled               BOOLEAN DEFAULT true,
  notes                 TEXT,
  synced_at             TIMESTAMP WITHOUT TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_duo_integrations_account ON duo_integrations(duo_account_id);
