-- =============================================================================
-- VIBN fs_* tables + agent_sessions migration
-- Run once against the production Coolify Postgres database.
--
-- These tables back the live app (fs_ prefix = "Firestore-shaped" flexible
-- JSONB rows that replaced the original Firebase collections).
--
-- Safe to re-run — all statements use IF NOT EXISTS / ON CONFLICT.
-- =============================================================================

-- Enable uuid support (safe no-op if already enabled)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ---------------------------------------------------------------------------
-- fs_users  (mirrors Firebase Auth + Firestore user docs)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fs_users (
  id          TEXT PRIMARY KEY,           -- gen_random_uuid()::text at insert time
  user_id     TEXT,                       -- NextAuth User.id (cuid)
  data        JSONB NOT NULL DEFAULT '{}',
  created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS fs_users_email_idx
  ON fs_users ((data->>'email'));

CREATE INDEX IF NOT EXISTS fs_users_user_id_idx
  ON fs_users (user_id);

-- ---------------------------------------------------------------------------
-- fs_projects  (Firestore projects collection)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fs_projects (
  id          TEXT PRIMARY KEY,           -- randomUUID() at insert time
  user_id     TEXT NOT NULL,              -- FK → fs_users.id
  workspace   TEXT NOT NULL,
  slug        TEXT NOT NULL UNIQUE,
  data        JSONB NOT NULL DEFAULT '{}',
  created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS fs_projects_user_idx
  ON fs_projects (user_id);

CREATE INDEX IF NOT EXISTS fs_projects_workspace_idx
  ON fs_projects (workspace);

CREATE INDEX IF NOT EXISTS fs_projects_slug_idx
  ON fs_projects (slug);

-- ---------------------------------------------------------------------------
-- fs_sessions  (AI coding session logs)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fs_sessions (
  id          TEXT PRIMARY KEY,
  user_id     TEXT,
  data        JSONB NOT NULL DEFAULT '{}',
  created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS fs_sessions_user_idx
  ON fs_sessions (user_id);

CREATE INDEX IF NOT EXISTS fs_sessions_project_idx
  ON fs_sessions ((data->>'projectId'));

-- ---------------------------------------------------------------------------
-- agent_sessions  (vibn-agent-runner execution records)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS agent_sessions (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  project_id      TEXT NOT NULL,          -- fs_projects.id (TEXT)
  app_name        TEXT NOT NULL,
  app_path        TEXT NOT NULL,
  task            TEXT NOT NULL,
  plan            JSONB,
  status          TEXT NOT NULL DEFAULT 'pending',
  output          JSONB NOT NULL DEFAULT '[]'::jsonb,
  changed_files   JSONB NOT NULL DEFAULT '[]'::jsonb,
  error           TEXT,
  started_at      TIMESTAMPTZ,
  completed_at    TIMESTAMPTZ,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS agent_sessions_project_idx
  ON agent_sessions (project_id, created_at DESC);

CREATE INDEX IF NOT EXISTS agent_sessions_status_idx
  ON agent_sessions (status);

-- ---------------------------------------------------------------------------
-- agent_session_events  (append-only timeline for SSE + replay)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS agent_session_events (
  id              BIGSERIAL PRIMARY KEY,
  session_id      UUID NOT NULL REFERENCES agent_sessions(id) ON DELETE CASCADE,
  project_id      TEXT NOT NULL,
  seq             INT NOT NULL,
  ts              TIMESTAMPTZ NOT NULL,
  type            TEXT NOT NULL,
  payload         JSONB NOT NULL DEFAULT '{}'::jsonb,
  client_event_id UUID UNIQUE,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE(session_id, seq)
);

CREATE INDEX IF NOT EXISTS agent_session_events_session_seq_idx
  ON agent_session_events (session_id, seq);

-- ---------------------------------------------------------------------------
-- NextAuth / Prisma tables  (required by PrismaAdapter + strategy:"database")
-- Only created if not already present from a prisma migrate run.
-- ---------------------------------------------------------------------------

CREATE TABLE IF NOT EXISTS users (
  id              TEXT PRIMARY KEY,
  name            TEXT,
  email           TEXT UNIQUE,
  email_verified  TIMESTAMPTZ,
  image           TEXT
);

CREATE TABLE IF NOT EXISTS accounts (
  id                  TEXT PRIMARY KEY,
  user_id             TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  type                TEXT NOT NULL,
  provider            TEXT NOT NULL,
  provider_account_id TEXT NOT NULL,
  refresh_token       TEXT,
  access_token        TEXT,
  expires_at          INTEGER,
  token_type          TEXT,
  scope               TEXT,
  id_token            TEXT,
  session_state       TEXT,
  UNIQUE (provider, provider_account_id)
);

CREATE TABLE IF NOT EXISTS sessions (
  id            TEXT PRIMARY KEY,
  session_token TEXT UNIQUE NOT NULL,
  user_id       TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  expires       TIMESTAMPTZ NOT NULL
);

CREATE TABLE IF NOT EXISTS verification_tokens (
  identifier  TEXT NOT NULL,
  token       TEXT UNIQUE NOT NULL,
  expires     TIMESTAMPTZ NOT NULL,
  UNIQUE (identifier, token)
);

-- ---------------------------------------------------------------------------
-- fs_chat_threads  (Vibn AI chat conversation threads)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fs_chat_threads (
  id         TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  user_id    TEXT NOT NULL,
  workspace  TEXT NOT NULL DEFAULT '',
  data       JSONB NOT NULL DEFAULT '{}',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS fs_chat_threads_user_ws_idx
  ON fs_chat_threads (user_id, workspace, updated_at DESC);

-- ---------------------------------------------------------------------------
-- fs_chat_messages  (individual messages within a thread)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fs_chat_messages (
  id         BIGSERIAL PRIMARY KEY,
  thread_id  TEXT NOT NULL REFERENCES fs_chat_threads(id) ON DELETE CASCADE,
  user_id    TEXT NOT NULL,
  data       JSONB NOT NULL DEFAULT '{}',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS fs_chat_messages_thread_idx
  ON fs_chat_messages (thread_id, created_at ASC);

-- Done
SELECT 'Migration complete' AS status;
