CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  username TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  password_hash TEXT NOT NULL,
  role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('user', 'admin')),
  email TEXT NOT NULL DEFAULT '',
  avatar_url TEXT NOT NULL DEFAULT '',
  state TEXT NOT NULL DEFAULT '',
  created_at TEXT NOT NULL
);

CREATE UNIQUE INDEX IF NOT EXISTS users_email_lower_uidx
  ON users (lower(email))
  WHERE email <> '';

CREATE TABLE IF NOT EXISTS posts (
  id TEXT PRIMARY KEY,
  parent_id TEXT REFERENCES posts(id) ON DELETE CASCADE,
  author_id TEXT NOT NULL REFERENCES users(id),
  title TEXT NOT NULL DEFAULT '',
  body TEXT NOT NULL,
  city TEXT NOT NULL DEFAULT '',
  post_date TEXT NOT NULL DEFAULT '',
  post_state TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  CONSTRAINT posts_shape_check CHECK (
    (parent_id IS NULL AND title <> '' AND post_date <> '')
    OR
    (parent_id IS NOT NULL AND title = '' AND city = '' AND post_date = '')
  )
);

CREATE INDEX IF NOT EXISTS idx_posts_parent_created
  ON posts(parent_id, created_at, id);

CREATE INDEX IF NOT EXISTS idx_posts_author_created
  ON posts(author_id, created_at DESC, id DESC);

CREATE INDEX IF NOT EXISTS idx_posts_root_date
  ON posts(post_date, post_state)
  WHERE parent_id IS NULL;

CREATE TABLE IF NOT EXISTS post_votes (
  user_id TEXT NOT NULL REFERENCES users(id),
  post_id TEXT NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
  value INTEGER NOT NULL CHECK (value IN (-1, 1)),
  PRIMARY KEY (user_id, post_id)
);

CREATE INDEX IF NOT EXISTS idx_post_votes_post_id
  ON post_votes(post_id);

CREATE TABLE IF NOT EXISTS sessions (
  token TEXT PRIMARY KEY,
  data BYTEA NOT NULL,
  expiry TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS sessions_expiry_idx ON sessions (expiry);
