CREATE TABLE dumps (
  id          TEXT    PRIMARY KEY,
  kind        TEXT    NOT NULL,
  title       TEXT    NOT NULL,
  comment     TEXT,
  user_id     TEXT    NOT NULL,
  created_at  TEXT    NOT NULL,
  updated_at  TEXT,
  url         TEXT,
  rich_content TEXT,
  file_name   TEXT,
  file_mime   TEXT,
  file_size   INTEGER,
  vote_count  INTEGER NOT NULL DEFAULT 0,
  is_private  INTEGER NOT NULL DEFAULT 0,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE users (
  id            TEXT PRIMARY KEY,
  username      TEXT NOT NULL UNIQUE,
  password_hash TEXT NOT NULL,
  is_admin      INTEGER NOT NULL DEFAULT 0,
  created_at    TEXT NOT NULL,
  updated_at    TEXT,
  avatar_mime   TEXT,
  invited_by    TEXT REFERENCES users(id)
);

CREATE TABLE votes (
  dump_id    TEXT NOT NULL,
  user_id    TEXT NOT NULL,
  created_at TEXT NOT NULL,
  PRIMARY KEY (dump_id, user_id),
  FOREIGN KEY (dump_id)  REFERENCES dumps(id) ON DELETE CASCADE,
  FOREIGN KEY (user_id)  REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE playlists (
  id          TEXT    PRIMARY KEY,
  user_id     TEXT    NOT NULL,
  title       TEXT    NOT NULL,
  description TEXT,
  is_public   INTEGER NOT NULL DEFAULT 1,
  created_at  TEXT    NOT NULL,
  updated_at  TEXT,
  image_mime  TEXT,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE playlist_dumps (
  playlist_id TEXT    NOT NULL,
  dump_id     TEXT    NOT NULL,
  position    INTEGER NOT NULL,
  added_at    TEXT    NOT NULL,
  PRIMARY KEY (playlist_id, dump_id),
  FOREIGN KEY (playlist_id) REFERENCES playlists(id) ON DELETE CASCADE,
  FOREIGN KEY (dump_id)     REFERENCES dumps(id)     ON DELETE CASCADE
);

CREATE TABLE comments (
  id         TEXT    PRIMARY KEY,
  dump_id    TEXT    NOT NULL,
  user_id    TEXT    NOT NULL,
  parent_id  TEXT,
  body       TEXT    NOT NULL,
  created_at TEXT    NOT NULL,
  updated_at TEXT,
  deleted    INTEGER NOT NULL DEFAULT 0,
  FOREIGN KEY (dump_id)   REFERENCES dumps(id)    ON DELETE CASCADE,
  FOREIGN KEY (user_id)   REFERENCES users(id)    ON DELETE CASCADE,
  FOREIGN KEY (parent_id) REFERENCES comments(id) ON DELETE CASCADE
);

CREATE INDEX idx_dumps_user           ON dumps(user_id);
CREATE INDEX idx_votes_user           ON votes(user_id);
CREATE INDEX idx_playlists_user       ON playlists(user_id);
CREATE INDEX idx_playlist_dumps_order ON playlist_dumps(playlist_id, position);
CREATE INDEX idx_playlist_dumps_dump  ON playlist_dumps(dump_id);
CREATE INDEX idx_comments_dump        ON comments(dump_id, created_at);

CREATE TABLE follows (
  id                   TEXT    PRIMARY KEY,
  follower_id          TEXT    NOT NULL,
  followed_user_id     TEXT,
  followed_playlist_id TEXT,
  created_at           TEXT    NOT NULL,
  FOREIGN KEY (follower_id)           REFERENCES users(id)     ON DELETE CASCADE,
  FOREIGN KEY (followed_user_id)      REFERENCES users(id)     ON DELETE CASCADE,
  FOREIGN KEY (followed_playlist_id)  REFERENCES playlists(id) ON DELETE CASCADE,
  CHECK (
    (followed_user_id IS NOT NULL AND followed_playlist_id IS NULL)
    OR
    (followed_user_id IS NULL AND followed_playlist_id IS NOT NULL)
  )
);

CREATE UNIQUE INDEX idx_follows_user
  ON follows(follower_id, followed_user_id)
  WHERE followed_user_id IS NOT NULL;

CREATE UNIQUE INDEX idx_follows_playlist
  ON follows(follower_id, followed_playlist_id)
  WHERE followed_playlist_id IS NOT NULL;

CREATE INDEX idx_follows_follower ON follows(follower_id);

CREATE TABLE invites (
  token       TEXT PRIMARY KEY,
  inviter_id  TEXT NOT NULL,
  used_at     TEXT,
  created_at  TEXT NOT NULL,
  FOREIGN KEY (inviter_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE notifications (
  id         TEXT    PRIMARY KEY,
  user_id    TEXT    NOT NULL,
  type       TEXT    NOT NULL,
  data       TEXT    NOT NULL,
  read       INTEGER NOT NULL DEFAULT 0,
  created_at TEXT    NOT NULL,
  source_key TEXT,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_notifications_user ON notifications(user_id, created_at);
CREATE UNIQUE INDEX idx_notifications_dedup
  ON notifications(user_id, source_key)
  WHERE source_key IS NOT NULL;
