CREATE EXTENSION citext;
CREATE TABLE users(
    id          UUID        NOT NULL PRIMARY KEY,
    handle      CITEXT      NOT NULL UNIQUE,
    password    TEXT,
    profpic     TEXT
);
CREATE TABLE sessions (
    id          UUID        NOT NULL PRIMARY KEY,
    token       BYTEA       NOT NULL UNIQUE,
    user_id     UUID        NOT NULL REFERENCES users(id),
    expiry      TIMESTAMPTZ NOT NULL,

    revoked     BOOLEAN     NOT NULL DEFAULT FALSE,
    revoked_at  TIMESTAMPTZ DEFAULT NULL,
    revoked_by  UUID        DEFAULT NULL REFERENCES users(id),

    CHECK(
        (revoked = FALSE AND revoked_at IS NULL     AND revoked_by IS NULL) OR
        (revoked = TRUE  AND revoked_at IS NOT NULL AND revoked_by IS NOT NULL)
    )
);
CREATE INDEX sessions_by_userid ON sessions(user_id);
CREATE TABLE user_permissions (
    user_id     UUID        NOT NULL REFERENCES users(id),
    permission  TEXT        NOT NULL,
    state       BOOLEAN     NOT NULL,
    PRIMARY KEY (user_id, permission)
);

CREATE TABLE quotes (
    id          UUID        NOT NULL PRIMARY KEY,
    timestamp   TIMESTAMP   NOT NULL,
    location    TEXT        DEFAULT NULL,
    context     TEXT        DEFAULT NULL,
    created_by  UUID        REFERENCES users(id),
    public      BOOLEAN     DEFAULT FALSE,
    fts         TSVECTOR    NOT NULL DEFAULT ''::tsvector -- TODO: trigger??
);
CREATE INDEX quotes_by_creation_user ON quotes(created_by);
CREATE TABLE persons (
    id          UUID        NOT NULL PRIMARY KEY,
    bio         TEXT        DEFAULT NULL,
    profpic     TEXT        DEFAULT NULL
);
CREATE TABLE names (
    id          UUID        NOT NULL PRIMARY KEY,
    name        CITEXT      NOT NULL,
    is_primary  BOOLEAN     NOT NULL DEFAULT FALSE,
    person_id   UUID        NOT NULL REFERENCES persons(id)
);
CREATE INDEX names_by_personid ON names(person_id);
CREATE UNIQUE INDEX no_name_duplicate_for_same_person ON names(person_id, name);
CREATE UNIQUE INDEX primary_name_uniqueness ON names(person_id) WHERE is_primary = TRUE;
CREATE TABLE lines (
    id          UUID        NOT NULL PRIMARY KEY,
    quote_id    UUID        NOT NULL REFERENCES quotes(id),
    ordering    SMALLINT    NOT NULL,
    content     TEXT        NOT NULL
);
CREATE INDEX lines_by_quoteid ON lines(quote_id);
CREATE UNIQUE INDEX lines_unique_ordering ON lines(quote_id, ordering);
CREATE TABLE line_authors (
    line_id     UUID        REFERENCES lines(id),
    name_id     UUID        REFERENCES names(id),
    PRIMARY KEY (line_id, name_id)
);

CREATE TABLE tags (
    id          UUID        NOT NULL PRIMARY KEY,
    name        CITEXT      NOT NULL UNIQUE
);

CREATE TABLE user_quote_likes (
    quote_id    UUID        NOT NULL REFERENCES quotes(id),
    user_id     UUID        NOT NULL REFERENCES users(id),
    PRIMARY KEY (quote_id, user_id)
);
CREATE INDEX quote_likes_by_user ON user_quote_likes(user_id);
CREATE INDEX quote_likes_by_quote ON user_quote_likes(quote_id);

CREATE TABLE quote_tags (
    quote_id    UUID        NOT NULL REFERENCES quotes(id),
    tag_id      UUID        NOT NULL REFERENCES tags(id),
    PRIMARY KEY (quote_id, tag_id)
);
CREATE INDEX quote_tags_by_quote ON quote_tags(quote_id);
CREATE INDEX quote_tags_by_tag ON quote_tags(tag_id);

CREATE TABLE logs (
    id          UUID        NOT NULL PRIMARY KEY,
    actor       UUID        NOT NULL REFERENCES users(id),
    target      UUID,
    actiontype  TEXT        NOT NULL,
    payload     JSONB
);
CREATE INDEX logs_by_actor ON logs(actor);
CREATE INDEX logs_by_target ON logs(target);
